Issues (1270)

src/Bootstrap.php (4 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace RssApp;
6
7
use Doctrine\Common\Annotations\AnnotationException;
8
use Doctrine\Common\Annotations\AnnotationReader;
9
use Doctrine\Common\Annotations\AnnotationRegistry;
10
use Doctrine\Common\Cache\ArrayCache;
11
use Doctrine\Common\Cache\RedisCache;
12
use Doctrine\Common\Proxy\AbstractProxyFactory;
13
use Doctrine\DBAL\DBALException;
14
use Doctrine\DBAL\DriverManager;
15
use Doctrine\ORM\Cache\DefaultCacheFactory;
16
use Doctrine\ORM\Cache\RegionsConfiguration;
17
use Doctrine\ORM\EntityManager;
18
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
19
use Doctrine\ORM\Mapping\UnderscoreNamingStrategy;
20
use Doctrine\ORM\ORMException;
21
use Doctrine\ORM\Tools\Setup;
22
use Exception;
23
use JMS\Serializer\SerializerBuilder;
24
use Redis;
25
use RssApp\Components\Registry;
26
use RssApp\Components\Twig\Filters;
27
use RssApp\Components\Twig\Functions;
28
use RssApp\Model\Extension\BacktickQuoteStrategy;
29
use Symfony\Bundle\FrameworkBundle\Routing\AnnotatedRouteControllerLoader;
30
use Symfony\Component\Config\FileLocator;
31
use Symfony\Component\HttpFoundation\Request;
32
use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader;
33
use Symfony\Component\Routing\RequestContext;
34
use Symfony\Component\Routing\Router;
35
use Twig\Environment;
36
use Twig\Loader\FilesystemLoader;
37
use Zend\Diactoros\ServerRequestFactory;
38
39
/**
40
 * @internal Intended to be a final abstract (or static) class (https://wiki.php.net/rfc/abstract_final_class)
41
 */
42
abstract class Bootstrap
43
{
44
45
    /**
46
     * Runs the class methods in order of declaration
47
     *
48
     * @param array $omitMethods
49
     *
50
     * @throws Exception
51
     */
52
    public static function initialize($omitMethods = []): void
53
    {
54
        $methods = get_class_methods(self::class);
55
        $key = array_search('initialize', $methods);
56
        if ($key !== false) {
57
            unset($methods[$key]);
58
        }
59
        foreach ($omitMethods as $omitMethod) {
60
            $omitKey = array_search($omitMethod, $methods);
61
            if ($omitKey !== false) {
62
                unset($methods[$key]);
63
            }
64
        }
65
        foreach ($methods as $method) {
66
            if (self::{$method}() === false) {
67
                throw new Exception($method.' failed to initialize');
68
            }
69
        }
70
    }
71
72
    protected static function redis(): bool
73
    {
74
        if (!empty(getenv('CACHE_HOST'))) {
75
            $redis = new Redis();
76
            $redis->pconnect(getenv('CACHE_HOST'), (int) getenv('CACHE_PORT'));
77
            $redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_IGBINARY);
78
            $redis->select(1);
79
            Registry::set('redis', $redis);
80
        } else {
81
            Registry::set('redis', false);
82
        }
83
        return true;
84
    }
85
86
    /**
87
     * @throws AnnotationException
88
     * @throws ORMException
89
     * @throws \Doctrine\DBAL\DBALException
90
     */
91
    protected static function orm(): bool
92
    {
93
        $config = Setup::createAnnotationMetadataConfiguration([BASEPATH.DS.'src'], true);
94
95
        $config->setAutoGenerateProxyClasses(AbstractProxyFactory::AUTOGENERATE_FILE_NOT_EXISTS);
96
        $config->setProxyDir(BASEPATH.DS.'tmp'.DS.'proxies');
97
        $config->addEntityNamespace('RssApp', 'RssApp\Model');
98
        $config->setQuoteStrategy(new BacktickQuoteStrategy());
99
        $config->setNamingStrategy(new UnderscoreNamingStrategy());
100
101
        if (Registry::get('redis')) {
102
            $ormCache = new RedisCache();
103
            $ormCache->setRedis(Registry::get('redis'));
0 ignored issues
show
It seems like RssApp\Components\Registry::get('redis') can also be of type null; however, parameter $redis of Doctrine\Common\Cache\RedisCache::setRedis() does only seem to accept Redis, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

103
            $ormCache->setRedis(/** @scrutinizer ignore-type */ Registry::get('redis'));
Loading history...
104
        } else {
105
            $ormCache = new ArrayCache();
106
        }
107
        $config->setSecondLevelCacheEnabled();
108
        $config->getSecondLevelCacheConfiguration()
109
            ->setCacheFactory(new DefaultCacheFactory(new RegionsConfiguration(), $ormCache));
110
        $config->setMetadataCacheImpl($ormCache);
111
        $config->setQueryCacheImpl($ormCache);
112
        $config->setResultCacheImpl($ormCache);
113
        $reader = new AnnotationReader();
114
        $driver = new AnnotationDriver($reader, [BASEPATH.DS.'src']);
115
        $config->setMetadataDriverImpl($driver);
0 ignored issues
show
$driver of type Doctrine\ORM\Mapping\Driver\AnnotationDriver is incompatible with the type Doctrine\Common\Persiste...ng\Driver\MappingDriver expected by parameter $driverImpl of Doctrine\ORM\Configurati...setMetadataDriverImpl(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

115
        $config->setMetadataDriverImpl(/** @scrutinizer ignore-type */ $driver);
Loading history...
116
117
        $slaves = [];
118
        if (getenv('DB_SLAVES') !== false) {
119
            $slaveHosts = explode(',', getenv('DB_SLAVES'));
120
            foreach ($slaveHosts as $host) {
121
                $slaves[] = [
122
                    'user'      => getenv('DB_USER'),
123
                    'password'  => getenv('DB_PASS'),
124
                    'host'      => $host,
125
                    'dbname'    => getenv('DB_NAME'),
126
                ];
127
            }
128
        } else {
129
            $slaves[] = [
130
                'user'      => getenv('DB_USER'),
131
                'password'  => getenv('DB_PASS'),
132
                'host'      => getenv('DB_HOST'),
133
                'dbname'    => getenv('DB_NAME'),
134
            ];
135
        }
136
        $connection = DriverManager::getConnection([
137
            'wrapperClass' => 'Doctrine\DBAL\Connections\MasterSlaveConnection',
138
            'driver' => 'pdo_mysql',
139
            'master' => [
140
                'user'      => getenv('DB_USER'),
141
                'password'  => getenv('DB_PASS'),
142
                'host'      => getenv('DB_HOST'),
143
                'dbname'    => getenv('DB_NAME'),
144
            ],
145
            'slaves' => $slaves,
146
        ]);
147
        $entityManager = EntityManager::create($connection, $config);
148
        Registry::set('em', $entityManager);
149
150
        try {
151
            $dbPlatform = $entityManager->getConnection()->getDatabasePlatform();
152
            $dbPlatform->registerDoctrineTypeMapping('enum', 'string');
153
            $dbPlatform->registerDoctrineTypeMapping('bit', 'boolean');
154
        } catch (DBALException $e) {
155
            echo $e->getMessage();
156
            return false;
157
        }
158
        AnnotationRegistry::registerAutoloadNamespace('JMS\Serializer\Annotation', BASEPATH.DS.'external/jms/serializer/src');
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\Common\Annotati...sterAutoloadNamespace() has been deprecated: this method is deprecated and will be removed in doctrine/annotations 2.0 autoloading should be deferred to the globally registered autoloader by then. For now, use @example AnnotationRegistry::registerLoader('class_exists') ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

158
        /** @scrutinizer ignore-deprecated */ AnnotationRegistry::registerAutoloadNamespace('JMS\Serializer\Annotation', BASEPATH.DS.'external/jms/serializer/src');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
159
        Registry::set('serializer', SerializerBuilder::create()->addMetadataDir(BASEPATH.DS.'src')->build());
160
        return true;
161
    }
162
163
    protected static function request(): bool
164
    {
165
        $request = ServerRequestFactory::fromGlobals($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES);
166
        Registry::set('request', $request);
167
        return true;
168
    }
169
170
    protected static function router(): bool
171
    {
172
        $request = Request::createFromGlobals();
173
        $requestContext = new RequestContext();
174
        $requestContext->fromRequest($request);
175
        $logger = Registry::get('log');
176
        $fileLocator = new FileLocator([
177
            BASEPATH.DS.'src'.DS.'Controller',
178
        ]);
179
        $reader = new AnnotationReader();
180
        $annotatedLoader = new AnnotatedRouteControllerLoader($reader);
181
        $loader = new AnnotationDirectoryLoader($fileLocator, $annotatedLoader);
182
        $router = new Router($loader, BASEPATH.DS.'src'.DS.'Controller', [], $requestContext, $logger);
183
        $loader = require BASEPATH.DS.'external'.DS.'autoload.php';
184
        AnnotationRegistry::registerLoader([$loader, 'loadClass']);
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\Common\Annotati...istry::registerLoader() has been deprecated: this method is deprecated and will be removed in doctrine/annotations 2.0 autoloading should be deferred to the globally registered autoloader by then. For now, use @example AnnotationRegistry::registerLoader('class_exists') ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

184
        /** @scrutinizer ignore-deprecated */ AnnotationRegistry::registerLoader([$loader, 'loadClass']);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
185
        Registry::set('router', $router);
186
        return true;
187
    }
188
189
    protected static function twig(): bool
190
    {
191
        $cache = false;
192
        if (APPLICATION_ENV !== 'dev') {
193
            $cache = BASEPATH.DS.'tmp'.DS.'view-cache';
194
        }
195
        $loader = new FilesystemLoader(BASEPATH.DS.'views');
196
        $twig = new Environment($loader, ['cache' => $cache]);
197
198
        $twig->addGlobal('request', Registry::get('request'));
199
        $twig->addGlobal('basePath', BASEPATH);
200
        $twig->addGlobal('applicationEnv', APPLICATION_ENV);
201
202
        foreach (Filters::all() as $filter) {
203
            $twig->addFilter($filter);
204
        }
205
        foreach (Functions::all() as $function) {
206
            $twig->addFunction($function);
207
        }
208
209
        Registry::set('twig', $twig);
210
        return true;
211
    }
212
213
}
214