Passed
Pull Request — main (#72)
by Felix
05:39 queued 02:45
created

Builder::configureRestler()   A

Complexity

Conditions 6
Paths 7

Size

Total Lines 33
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 6.1666

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 6
eloc 19
c 2
b 0
f 0
nc 7
nop 1
dl 0
loc 33
ccs 15
cts 18
cp 0.8333
crap 6.1666
rs 9.0111
1
<?php
2
namespace Aoe\Restler\System\Restler;
3
4
/***************************************************************
5
 *  Copyright notice
6
 *
7
 *  (c) 2015 AOE GmbH <[email protected]>
8
 *
9
 *  All rights reserved
10
 *
11
 *  This script is part of the TYPO3 project. The TYPO3 project is
12
 *  free software; you can redistribute it and/or modify
13
 *  it under the terms of the GNU General Public License as published by
14
 *  the Free Software Foundation; either version 3 of the License, or
15
 *  (at your option) any later version.
16
 *
17
 *  The GNU General Public License can be found at
18
 *  http://www.gnu.org/copyleft/gpl.html.
19
 *
20
 *  This script is distributed in the hope that it will be useful,
21
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 *  GNU General Public License for more details.
24
 *
25
 *  This copyright notice MUST APPEAR in all copies of the script!
26
 ***************************************************************/
27
28
use Aoe\Restler\Configuration\ExtensionConfiguration;
29
use Aoe\Restler\System\TYPO3\Cache;
30
use InvalidArgumentException;
31
use Luracast\Restler\Defaults;
32
use Luracast\Restler\Scope;
33
use Psr\Http\Message\ServerRequestInterface;
34
use TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend;
35
use TYPO3\CMS\Core\Cache\CacheManager;
36
use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException;
37
use TYPO3\CMS\Core\Core\Environment;
38
use TYPO3\CMS\Core\SingletonInterface;
39
use TYPO3\CMS\Core\Utility\GeneralUtility;
40
use TYPO3\CMS\Extbase\Object\ObjectManager;
41
42
/**
43
 * @package Restler
44
 */
45
class Builder implements SingletonInterface
46
{
47
    /**
48
     * @var ExtensionConfiguration
49
     */
50
    private $extensionConfiguration;
51
52
    /**
53
     * @var CacheManager
54
     */
55
    private $cacheManager;
56
57
    /**
58
     * @param ExtensionConfiguration $extensionConfiguration
59
     * @param CacheManager $cacheManager
60
     */
61 9
    public function __construct(ExtensionConfiguration $extensionConfiguration, CacheManager $cacheManager)
62
    {
63 9
        $this->extensionConfiguration = $extensionConfiguration;
64 9
        $this->cacheManager = $cacheManager;
65
    }
66
67
    /**
68
     * initialize and configure restler-framework and return restler-object
69
     *
70
     * @return RestlerExtended
71
     */
72
    public function build(ServerRequestInterface $request = null)
73
    {
74
        $this->setAutoLoading();
75
        $this->setCacheDirectory();
76
        $this->setServerConfiguration();
77
78
        $restlerObj = $this->createRestlerObject($request);
79
        $this->configureRestler($restlerObj);
80
        $this->addApiClassesByGlobalArray($restlerObj);
81
        return $restlerObj;
82
    }
83
84
    /**
85
     * @return RestlerExtended
86
     */
87 1
    protected function createRestlerObject(ServerRequestInterface $request = null)
88
    {
89 1
        return new RestlerExtended(
90 1
            GeneralUtility::makeInstance(Cache::class),
91 1
            $this->extensionConfiguration->isProductionContextSet(),
92 1
            $this->extensionConfiguration->isCacheRefreshingEnabled(),
93
            $request
94
        );
95
    }
96
97
    /**
98
     * Call all classes, which implements the interface 'Aoe\Restler\System\Restler\ConfigurationInterface'.
99
     * Those classes includes further restler-configurations, e.g.:
100
     *  - add API-classes
101
     *  - add authentication-classes
102
     *  - configure/set properties of several classes inside the restler-framework
103
     *  - configure overwriting of several classes inside the restler-framework
104
     *
105
     * @param RestlerExtended $restler
106
     * @throws InvalidArgumentException
107
     */
108 4
    private function configureRestler(RestlerExtended $restler)
109
    {
110 4
        $restlerConfigurationClasses = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['restler']['restlerConfigurationClasses'];
111
112 4
        if (false === is_array($restlerConfigurationClasses) || count($restlerConfigurationClasses) === 0) {
113 2
            $message = 'No restler-configuration-class found (at least one restler-configuration-class is required)! ';
114 2
            $message .= 'The configuration-class must be registered in ext_localconf.php of your TYPO3-extension like this: ';
115 2
            $message .= '$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'restler\'][\'restlerConfigurationClasses\'][] =
116
                \'[YourConfigurationClass]\';';
117 2
            $message .= 'The configuration-class must implement this interface: Aoe\Restler\System\Restler\ConfigurationInterface';
118 2
            throw new InvalidArgumentException($message, 1428562059);
119
        }
120
121
        // append configuration classes from external GLOBAL registration
122 2
        if (is_array($GLOBALS['TYPO3_Restler']['restlerConfigurationClasses'])) {
123 2
            $externalRestlerConfigurationClasses = array_unique($GLOBALS['TYPO3_Restler']['restlerConfigurationClasses']);
124 2
            $restlerConfigurationClasses = array_merge(
125
                $restlerConfigurationClasses,
126
                $externalRestlerConfigurationClasses
127
            );
128
        }
129
130 2
        foreach ($restlerConfigurationClasses as $restlerConfigurationClass) {
131 2
            $configurationObj = GeneralUtility::makeInstance($restlerConfigurationClass);
132
133
            /* @var $configurationObj ConfigurationInterface */
134 2
            if (false === $configurationObj instanceof ConfigurationInterface) {
135
                $message = 'class "' . $restlerConfigurationClass . '" did not implement the ';
136
                $message .= 'interface "Aoe\Restler\System\Restler\ConfigurationInterface"!';
137
                throw new InvalidArgumentException($message, 1428562081);
138
            }
139
140 2
            $configurationObj->configureRestler($restler);
141
        }
142
    }
143
144
    /**
145
     * Add API-Controller-Classes that are registered by global array
146
     *
147
     * @param RestlerExtended $restler
148
     */
149 1
    private function addApiClassesByGlobalArray(RestlerExtended $restler)
150
    {
151 1
        $addApiController = $GLOBALS['TYPO3_Restler']['addApiClass'];
152 1
        if (is_array($addApiController)) {
153 1
            foreach ($addApiController as $apiEndpoint => $apiControllers) {
154 1
                $uniqueApiControllers = array_unique($apiControllers);
155 1
                foreach ($uniqueApiControllers as $apiController) {
156 1
                    $restler->addAPIClass($apiController, $apiEndpoint);
157
                }
158
            }
159
        }
160
    }
161
162
    /**
163
     * use auto-loading for PHP-classes of restler-framework and Extbase/TYPO3 (use dependency-injection of Extbase)
164
     */
165 1
    private function setAutoLoading()
166
    {
167
        // set auto-loading for Extbase/TYPO3-classes
168 1
        Scope::$resolver = function ($className) {
169
            // @TODO TYPO3 v12:
170
            // Using of ObjectManager will be removed in TYPO3v12. Currently, we must use the ObjectManager here,
171
            // because it can happen, that e.g. the REST-controllers (which 3rd-party-extensions provide), are not
172
            // supporting the new dependency-injection (via symfony) of TYPO3!
173 1
            return GeneralUtility::makeInstance(ObjectManager::class)->get($className);
174
        };
175
    }
176
177
    /**
178
     * configure cache-directory (where restler can write cache-files)
179
     */
180 1
    private function setCacheDirectory()
181
    {
182 1
        Defaults::$cacheDirectory = $this->getCache()->getCacheDirectory();
183
    }
184
185
    /**
186
     * fix server-port (if not correct set)
187
     */
188 1
    private function setServerConfiguration()
189
    {
190 1
        if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' && $_SERVER['SERVER_PORT'] === '80') {
191
            // Fix port for HTTPS
192
            // Otherwise restler will create those urls for online-documentation, when HTTPS is used: https://www.example.com:80
193 1
            $_SERVER['SERVER_PORT'] = '443';
194
        }
195
    }
196
197
    /**
198
     * @return SimpleFileBackend
199
     * @throws NoSuchCacheException
200
     */
201 1
    private function getCache()
202
    {
203 1
        return $this->cacheManager->getCache('tx_restler_cache')->getBackend();
204
    }
205
}
206