Builder::addApiClassesByGlobalArray()   B
last analyzed

Complexity

Conditions 7
Paths 4

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 8.8142

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 8
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 10
ccs 2
cts 3
cp 0.6667
crap 8.8142
rs 8.8333
1
<?php
2
3
namespace Aoe\Restler\System\Restler;
4
5
/***************************************************************
6
 *  Copyright notice
7
 *
8
 *  (c) 2024 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 InvalidArgumentException;
32
use Luracast\Restler\Defaults;
33
use Luracast\Restler\Scope;
34
use Psr\Http\Message\ServerRequestInterface;
35
use TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend;
36
use TYPO3\CMS\Core\Cache\CacheManager;
37
use TYPO3\CMS\Core\SingletonInterface;
38
use TYPO3\CMS\Core\Utility\GeneralUtility;
39
40
class Builder implements SingletonInterface
41
{
42
    public function __construct(
43
        private readonly ExtensionConfiguration $extensionConfiguration,
44
        private readonly CacheManager $cacheManager,
45
    ) {
46
    }
47
48
    /**
49
     * initialize and configure restler-framework and return restler-object
50
     *
51
     * @return RestlerExtended
52 9
     */
53
    public function build(ServerRequestInterface $request = null)
54 9
    {
55 9
        $this->setAutoLoading();
56 9
        $this->setCacheDirectory();
57
        $this->setServerConfiguration();
58
59
        $restlerObj = $this->createRestlerObject($request);
60
        $this->configureRestler($restlerObj);
61
        $this->addApiClassesByGlobalArray($restlerObj);
62
        return $restlerObj;
63
    }
64
65
    protected function createRestlerObject(ServerRequestInterface $request = null): RestlerExtended
66
    {
67
        return new RestlerExtended(
68
            GeneralUtility::makeInstance(Cache::class),
69
            $this->extensionConfiguration->isProductionContextSet(),
70
            $this->extensionConfiguration->isCacheRefreshingEnabled(),
71
            $request
72
        );
73
    }
74
75 1
    /**
76
     * Call all classes, which implements the interface 'Aoe\Restler\System\Restler\ConfigurationInterface'.
77 1
     * Those classes includes further restler-configurations, e.g.:
78 1
     *  - add API-classes
79 1
     *  - add authentication-classes
80 1
     *  - configure/set properties of several classes inside the restler-framework
81
     *  - configure overwriting of several classes inside the restler-framework
82
     */
83
    private function configureRestler(RestlerExtended $restler): void
84
    {
85
        $restlerConfigurationClasses = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['restler']['restlerConfigurationClasses'];
86
87
        if (!is_array($restlerConfigurationClasses) || $restlerConfigurationClasses === []) {
88
            $message = 'No restler-configuration-class found (at least one restler-configuration-class is required)! ';
89
            $message .= 'The configuration-class must be registered in ext_localconf.php of your TYPO3-extension like this: ';
90
            $message .= '$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'restler\'][\'restlerConfigurationClasses\'][] =
91
                \'[YourConfigurationClass]\';';
92
            $message .= 'The configuration-class must implement this interface: Aoe\Restler\System\Restler\ConfigurationInterface';
93
            throw new InvalidArgumentException($message, 1428562059);
94
        }
95 4
96
        // append configuration classes from external GLOBAL registration
97 4
        if (isset($GLOBALS['TYPO3_Restler']['restlerConfigurationClasses']) && is_array(
98
            $GLOBALS['TYPO3_Restler']['restlerConfigurationClasses']
99 4
        )) {
100 2
            $externalRestlerConfigurationClasses = array_unique($GLOBALS['TYPO3_Restler']['restlerConfigurationClasses']);
101 2
            $restlerConfigurationClasses = array_merge(
102 2
                $restlerConfigurationClasses,
103
                $externalRestlerConfigurationClasses
104 2
            );
105 2
        }
106
107
        foreach ($restlerConfigurationClasses as $restlerConfigurationClass) {
108
            /** @var ConfigurationInterface $configurationObj */
109 2
            $configurationObj = GeneralUtility::makeInstance($restlerConfigurationClass);
110 2
111 2
            if (!$configurationObj instanceof ConfigurationInterface) {
112 2
                $message = 'class "' . $restlerConfigurationClass . '" did not implement the ';
113
                $message .= 'interface "Aoe\Restler\System\Restler\ConfigurationInterface"!';
114
                throw new InvalidArgumentException($message, 1428562081);
115
            }
116
117 2
            $configurationObj->configureRestler($restler);
118
        }
119 2
    }
120
121 2
    /**
122
     * Add API-Controller-Classes that are registered by global array
123
     */
124
    private function addApiClassesByGlobalArray(RestlerExtended $restler): void
125
    {
126
        if (array_key_exists('TYPO3_Restler', $GLOBALS) &&
127 2
            is_array($GLOBALS['TYPO3_Restler']) &&
128
            array_key_exists('addApiClass', $GLOBALS['TYPO3_Restler']) &&
129 2
            is_array($GLOBALS['TYPO3_Restler']['addApiClass'])) {
130
            foreach ($GLOBALS['TYPO3_Restler']['addApiClass'] as $apiEndpoint => $apiControllers) {
131
                $uniqueApiControllers = array_unique($apiControllers);
132
                foreach ($uniqueApiControllers as $apiController) {
133
                    $restler->addAPIClass($apiController, $apiEndpoint);
134 1
                }
135
            }
136 1
        }
137 1
    }
138 1
139 1
    /**
140 1
     * use autoload for PHP-classes of restler-framework and Extbase/TYPO3 (use dependency-injection of Extbase)
141 1
     */
142 1
    private function setAutoLoading(): void
143 1
    {
144
        // set autoload for Extbase/TYPO3-classes
145
        Scope::$resolver = static fn ($className): object => GeneralUtility::makeInstance($className);
146
    }
147 1
148
    /**
149
     * configure cache-directory (where restler can write cache-files)
150
     */
151
    private function setCacheDirectory(): void
152 1
    {
153
        Defaults::$cacheDirectory = $this->getCache()->getCacheDirectory();
154
    }
155 1
156
    /**
157 1
     * fix server-port (if not correct set)
158
     */
159
    private function setServerConfiguration(): void
160
    {
161
        if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' && $_SERVER['SERVER_PORT'] === '80') {
162
            // Fix port for HTTPS
163
            // Otherwise restler will create those urls for online-documentation, when HTTPS is used: https://www.example.com:80
164
            $_SERVER['SERVER_PORT'] = '443';
165
        }
166
    }
167
168
    /**
169
     * @return SimpleFileBackend
170
     */
171
    private function getCache()
172
    {
173
        return $this->cacheManager->getCache('tx_restler_cache')
174
            ->getBackend();
175
    }
176
}
177