Passed
Push — main ( 76fa26...4da44b )
by
unknown
03:01
created

Builder   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 158
Duplicated Lines 0 %

Test Coverage

Coverage 72.72%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 57
c 2
b 0
f 0
dl 0
loc 158
ccs 48
cts 66
cp 0.7272
rs 10
wmc 22

9 Methods

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