Completed
Push — master ( 5152c1...290c4d )
by Tim
02:12
created

injectPluginConfigurationService()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
/**
4
 * Abstract controller.
5
 */
6
declare(strict_types=1);
7
8
namespace HDNET\Calendarize\Controller;
9
10
use HDNET\Calendarize\Domain\Repository\IndexRepository;
11
use HDNET\Calendarize\Event\GenericActionAssignmentEvent;
12
use HDNET\Calendarize\Property\TypeConverter\AbstractBookingRequest;
13
use HDNET\Calendarize\Service\PluginConfigurationService;
14
use HDNET\Calendarize\Utility\DateTimeUtility;
15
use Psr\Http\Message\ResponseInterface;
16
use TYPO3\CMS\Core\Messaging\FlashMessage;
17
use TYPO3\CMS\Core\Utility\GeneralUtility;
18
use TYPO3\CMS\Core\Utility\HttpUtility;
19
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
20
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
21
use TYPO3\CMS\Extbase\Security\Cryptography\HashService;
22
use TYPO3\CMS\Frontend\Controller\ErrorController;
23
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
24
use TYPO3\CMS\Frontend\Page\PageAccessFailureReasons;
25
26
/**
27
 * Abstract controller.
28
 */
29
abstract class AbstractController extends ActionController
30
{
31
    /**
32
     * The index repository.
33
     *
34
     * @var \HDNET\Calendarize\Domain\Repository\IndexRepository
35
     */
36
    protected $indexRepository;
37
38
    /**
39
     * @var PluginConfigurationService
40
     */
41
    protected $pluginConfigurationService;
42
43
    /**
44
     * The feed formats and content types.
45
     *
46
     * @var array
47
     */
48
    protected $feedFormats = [
49
        'ics' => 'text/calendar',
50
        'xml' => 'application/xml',
51
        'atom' => 'application/rss+xml',
52
    ];
53
54
    /**
55
     * Inject plugin configuration service.
56
     *
57
     * @param PluginConfigurationService $pluginConfigurationService
58
     */
59
    public function injectPluginConfigurationService(PluginConfigurationService $pluginConfigurationService)
60
    {
61
        $this->pluginConfigurationService = $pluginConfigurationService;
62
    }
63
64
    /**
65
     * Inject index repository.
66
     *
67
     * @param \HDNET\Calendarize\Domain\Repository\IndexRepository $indexRepository
68
     */
69
    public function injectIndexRepository(IndexRepository $indexRepository)
70
    {
71
        $this->indexRepository = $indexRepository;
72
    }
73
74
    /**
75
     * Inject the configuration manager.
76
     *
77
     * @param ConfigurationManagerInterface $configurationManager
78
     */
79
    public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager)
80
    {
81
        $this->configurationManager = $configurationManager;
82
        $this->settings = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS);
83
        $this->settings = $this->pluginConfigurationService->respectPluginConfiguration((array)$this->settings);
84
    }
85
86
    /**
87
     * Init all actions.
88
     */
89
    public function initializeAction()
90
    {
91
        parent::initializeAction();
92
        AbstractBookingRequest::setConfigurations(GeneralUtility::trimExplode(',', $this->settings['configuration']));
93
    }
94
95
    /**
96
     * Calls the specified action method and passes the arguments.
97
     *
98
     * If the action returns a string, it is appended to the content in the
99
     * response object. If the action doesn't return anything and a valid
100
     * view exists, the view is rendered automatically.
101
     *
102
     * @api
103
     */
104
    protected function callActionMethod()
105
    {
106
        parent::callActionMethod();
107
        if (isset($this->feedFormats[$this->request->getFormat()])) {
108
            $this->sendHeaderAndFilename($this->feedFormats[$this->request->getFormat()], $this->request->getFormat());
109
            if ($this->request->hasArgument('hmac')) {
110
                $hmac = $this->request->getArgument('hmac');
111
                if ($this->validatePluginHmac($hmac)) {
0 ignored issues
show
Bug introduced by
It seems like $hmac defined by $this->request->getArgument('hmac') on line 110 can also be of type array; however, HDNET\Calendarize\Contro...r::validatePluginHmac() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
112
                    $this->sendHeaderAndFilename($this->feedFormats[$this->request->getFormat()], $this->request->getFormat());
113
                }
114
115
                return;
116
            }
117
            $this->sendHeaderAndFilename($this->feedFormats[$this->request->getFormat()], $this->request->getFormat());
118
        }
119
    }
120
121
    /**
122
     * Send the content type header and the right file extension in front of the content.
123
     *
124
     * @param $contentType
125
     * @param $fileExtension
126
     */
127
    protected function sendHeaderAndFilename($contentType, $fileExtension)
128
    {
129
        $testMode = (bool)$this->settings['feed']['debugMode'];
130
        if ($testMode) {
131
            header('Content-Type: text/plain; charset=utf-8');
132
        } else {
133
            header('Content-Type: ' . $contentType . '; charset=utf-8');
134
            header('Content-Disposition: inline; filename=calendar.' . $fileExtension);
135
        }
136
        switch ($this->request->getFormat()) {
137
            case 'ics':
138
                // Use CRLF, see https://tools.ietf.org/html/rfc5545#section-3.1
139
                echo str_replace("\n", "\r\n", $this->response->getContent());
140
                break;
141
            default:
142
                echo $this->response->getContent();
143
                break;
144
        }
145
        HttpUtility::setResponseCodeAndExit(HttpUtility::HTTP_STATUS_200);
146
    }
147
148
    /**
149
     * Extend the variables by the event and name and assign the variable to the view.
150
     */
151
    protected function eventExtendedAssignMultiple(array $variables, string $className, string $eventName)
152
    {
153
        // use this variable in your extension to add more custom variables
154
        $variables['extended'] = [];
155
        $variables['extended']['pluginHmac'] = $this->calculatePluginHmac();
156
        $variables['settings'] = $this->settings;
157
        $variables['contentObject'] = $this->configurationManager->getContentObject()->data;
158
159
        $event = new GenericActionAssignmentEvent($variables, $className, $eventName);
160
        $this->eventDispatcher->dispatch($event);
0 ignored issues
show
Documentation introduced by
$event is of type object<HDNET\Calendarize...cActionAssignmentEvent>, but the function expects a object<Psr\EventDispatcher\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
161
162
        $this->view->assignMultiple($event->getVariables());
163
    }
164
165
    /**
166
     * Return the controllerName, pluginName and actionName.
167
     *
168
     * @return string
169
     */
170
    protected function getStringForPluginHmac(): string
171
    {
172
        $actionMethodName = ucfirst($this->request->getControllerActionName());
173
        $pluginName = $this->request->getPluginName();
174
        $controllerName = $this->request->getControllerName();
175
176
        return $controllerName . $pluginName . $actionMethodName;
177
    }
178
179
    /**
180
     * Calculate the plugin Hmac.
181
     *
182
     * @return string $hmac
183
     *
184
     * @see \TYPO3\CMS\Extbase\Security\Cryptography\HashService::generateHmac()
185
     */
186
    protected function calculatePluginHmac()
187
    {
188
        $string = $this->getStringForPluginHmac();
189
190
        $hashService = GeneralUtility::makeInstance(HashService::class);
191
192
        return $hashService->generateHmac($string);
193
    }
194
195
    /**
196
     * \TYPO3\CMS\Extbase\Security\Cryptography\HashService::validateHmac().
197
     *
198
     * @param string $hmac
199
     *
200
     * @return bool
201
     */
202
    protected function validatePluginHmac(string $hmac): bool
203
    {
204
        $string = $this->getStringForPluginHmac();
205
206
        /** @var HashService $hashService */
207
        $hashService = GeneralUtility::makeInstance(HashService::class);
208
209
        return $hashService->validateHmac($string, $hmac);
210
    }
211
212
    /**
213
     * Check if the static template is included.
214
     */
215
    protected function checkStaticTemplateIsIncluded()
216
    {
217
        if (!isset($this->settings['dateFormat'])) {
218
            $this->addFlashMessage(
219
                'Basic configuration settings are missing. It seems, that the Static Extension TypoScript is not loaded to your TypoScript configuration. Please add the calendarize TS to your TS settings.',
220
                'Configuration Error',
221
                FlashMessage::ERROR
222
            );
223
        }
224
    }
225
226
    /**
227
     * Change the page title.
228
     *
229
     * @param string $title
230
     */
231
    protected function changePageTitle($title)
232
    {
233
        /** @var TypoScriptFrontendController $frontendController */
234
        $frontendController = $GLOBALS['TSFE'];
235
        $frontendController->page['title'] = $title;
236
        $frontendController->indexedDocTitle = $title;
237
    }
238
239
    /**
240
     * Add cache tags.
241
     *
242
     * @param array $tags
243
     */
244
    protected function addCacheTags(array $tags)
245
    {
246
        if ($GLOBALS['TSFE'] instanceof TypoScriptFrontendController) {
247
            $GLOBALS['TSFE']->addCacheTags($tags);
248
        }
249
    }
250
251
    protected function isDateOutOfTypoScriptConfiguration(\DateTime $dateTime): bool
252
    {
253
        $prev = DateTimeUtility::normalizeDateTimeSingle($this->settings['dateLimitBrowserPrev']);
254
        $next = DateTimeUtility::normalizeDateTimeSingle($this->settings['dateLimitBrowserNext']);
255
256
        return $prev > $dateTime || $next < $dateTime;
257
    }
258
259
    protected function return404Page(): ResponseInterface
260
    {
261
        return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
262
            $GLOBALS['TYPO3_REQUEST'],
263
            'The requested page does not exist',
264
            ['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
265
        );
266
    }
267
}
268