Passed
Push — develop ( 6f18ac...aef63b )
by Jens
02:33
created

CloudControl   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 302
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 302
rs 8.8
c 0
b 0
f 0
wmc 36

18 Methods

Rating   Name   Duplication   Size   Complexity  
A calculateRelativePath() 0 21 4
A iniSets() 0 8 1
A getRelativePath() 0 16 3
A createDir() 0 12 4
A saveConfig() 0 4 1
A run() 0 3 1
A cliServerServeResource() 0 10 4
A postUpdate() 0 4 1
A prepare() 0 16 1
B copyInstallFile() 0 19 5
A getConfig() 0 12 2
A removePointerToCurrentDir() 0 6 2
A setLocalisation() 0 4 1
A createCacheStorage() 0 4 1
A postInstall() 0 4 1
A createStorage() 0 4 1
A setInternalEncoding() 0 4 2
B checkInstall() 0 41 1
1
<?php
2
/**
3
 * Created by jensk on 14-8-2017.
4
 */
5
6
namespace CloudControl\Cms;
7
8
use CloudControl\Cms\cc\Application;
9
use CloudControl\Cms\storage\Cache;
10
use CloudControl\Cms\storage\Repository;
11
use Composer\Script\Event;
12
13
class CloudControl
14
{
15
    /**
16
     * @param $dir
17
     * @return \stdClass
18
     */
19
    public static function prepare($dir)
20
    {
21
        self::iniSets();
22
        self::setInternalEncoding();
23
        self::setLocalisation();
24
25
26
        ob_start('sanitize_output');
27
        session_start();
28
29
        $rootDir = realpath($dir . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR);
30
        $configPath = realpath($rootDir . DIRECTORY_SEPARATOR . 'config.json');
31
        $preparation = new \stdClass();
32
        $preparation->rootDir = $rootDir;
33
        $preparation->configPath = $configPath;
34
        return $preparation;
35
    }
36
37
    /**
38
     * @param string $rootDir
39
     * @param string $configPath
40
     * @throws \Exception
41
     */
42
    public static function run($rootDir, $configPath)
43
    {
44
        new Application($rootDir, $configPath);
45
    }
46
47
    public static function cliServerServeResource($dir)
48
    {
49
        if (PHP_SAPI === 'cli-server') {
50
            if (preg_match('/\.(?:js|ico|txt|gif|jpg|jpeg|png|bmp|css|html|htm|php|pdf|exe|eot|svg|ttf|woff|ogg|mp3|xml|map|scss)$/', $_SERVER['REQUEST_URI'])) {
51
                if (file_exists($dir . $_SERVER["REQUEST_URI"])) {
52
                    return true;    // serve the requested resource as-is.
53
                }
54
            }
55
        }
56
        return false;
57
    }
58
59
    /**
60
     * @param Composer\Script\Event $event
61
     */
62
    public static function postInstall($event)
63
    {
64
        $event->getIO()->write("Post install");
65
        self::checkInstall($event);
66
    }
67
68
    /**
69
     * @param Composer\Script\Event $event
70
     */
71
    public static function postUpdate($event)
72
    {
73
        $event->getIO()->write("Post update");
74
        self::checkInstall($event);
75
    }
76
77
    /**
78
     * @param Composer\Script\Event $event
79
     */
80
    private static function checkInstall($event)
81
    {
82
        $event->getIO()->write('');
83
        $event->getIO()->write('********************************************************');
84
        $event->getIO()->write('*** Checking installation of Cloud Control framework ***');
85
        $event->getIO()->write('********************************************************');
86
        $event->getIO()->write('');
87
88
        $vendorDir = $event->getComposer()->getConfig()->get('vendor-dir');
89
        $rootDir = realpath($vendorDir . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR);
90
91
        $baseConfigTargetPath = $rootDir . DIRECTORY_SEPARATOR . 'config.json';
92
        $configObject = self::getConfig($event, $baseConfigTargetPath);
93
94
        $configObject->{'templateDir'} = self::createDir($event, $rootDir, 'templates');
95
        $configObject->{'storageDir'} = self::createDir($event, $rootDir, $configObject->{'storageDir'});
96
        $configObject->{'publicDir'} = self::createDir($event, $rootDir, 'public');
97
        $configObject->{'jsDir'} = self::createDir($event, $rootDir, $configObject->{'publicDir'} . 'js');
98
        $configObject->{'cssDir'} = self::createDir($event, $rootDir, $configObject->{'publicDir'} . 'css');
99
        $configObject->{'imagesDir'} = self::createDir($event, $rootDir, $configObject->{'publicDir'} . 'images');
100
        $configObject->{'filesDir'} = self::createDir($event, $rootDir, $configObject->{'publicDir'} . 'files');
101
        $componentsDir = self::createDir($event, $rootDir, 'components');
102
103
        $baseStorageDefaultPath = __DIR__ . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR . '_storage.json';
104
        $baseStorageSqlPath = __DIR__ . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR . '_storage.sql';
105
        $baseCacheSqlPath = __DIR__ . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR . '_cache.sql';
106
107
        self::createStorage($configObject->{'storageDir'}, $baseStorageDefaultPath, $baseStorageSqlPath);
108
        self::createCacheStorage($rootDir . DIRECTORY_SEPARATOR . $configObject->{'storageDir'}, $baseCacheSqlPath);
109
        self::saveConfig($event, $baseConfigTargetPath, $configObject);
110
        self::copyInstallFile($event, 'public.htaccess', $configObject->{'publicDir'}, '.htaccess');
111
        self::copyInstallFile($event, 'root.htaccess', $rootDir, '.htaccess');
112
        self::copyInstallFile($event, 'base.php', $configObject->{'templateDir'});
113
        self::copyInstallFile($event, 'cms.css', $configObject->{'cssDir'});
114
        self::copyInstallFile($event, 'cms.js', $configObject->{'jsDir'});
115
        self::copyInstallFile($event, 'index.php', $configObject->{'publicDir'});
116
        self::copyInstallFile($event, 'CustomComponent.php', $componentsDir);
117
118
        $event->getIO()->write("");
119
        $event->getIO()->write("[SUCCESS] Installation is complete");
120
        $event->getIO()->write("");
121
    }
122
123
    /**
124
     * @param Composer\Script\Event $event
125
     * @param $baseConfigTargetPath
126
     * @param $configObject
127
     */
128
    private static function saveConfig($event, $baseConfigTargetPath, $configObject)
129
    {
130
        file_put_contents($baseConfigTargetPath, json_encode($configObject));
131
        $event->getIO()->write("[INFO] Saved config to: " . $baseConfigTargetPath);
132
    }
133
134
    /**
135
     * @param Composer\Script\Event $event
136
     * @param $sourceFileName
137
     * @param $destinationPath
138
     * @param null $destinationFileName
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $destinationFileName is correct as it would always require null to be passed?
Loading history...
139
     */
140
    private static function copyInstallFile($event, $sourceFileName, $destinationPath, $destinationFileName = null)
141
    {
142
        $sourceFilePath = realpath(__DIR__ . DIRECTORY_SEPARATOR . 'install/_' . $sourceFileName);
143
144
145
        if ($destinationFileName === null) {
146
            $destinationFileName = $sourceFileName;
147
        }
148
149
        if (file_exists($sourceFilePath) && realpath($destinationPath) !== false) {
150
            $destinationFullPath = realpath($destinationPath) . DIRECTORY_SEPARATOR . $destinationFileName;
151
            if (file_exists($destinationFullPath)) {
152
                $event->getIO()->write("[INFO] File already exists: " . $destinationFullPath);
153
            } else {
154
                copy($sourceFilePath, $destinationFullPath);
155
                $event->getIO()->write("[INSTALL] Copied file: " . $sourceFileName . ' to ' . $destinationPath);
156
            }
157
        } else {
158
            $event->getIO()->write("[ERROR] Couldnt copy file: " . $sourceFileName . ' to ' . $destinationPath);
159
        }
160
    }
161
162
    /**
163
     * @param $storageDir
164
     * @param $baseStorageDefaultPath
165
     * @param $baseStorageSqlPath
166
     */
167
    private static function createStorage($storageDir, $baseStorageDefaultPath, $baseStorageSqlPath)
168
    {
169
        $repository = new Repository($storageDir);
170
        $repository->init($baseStorageDefaultPath, $baseStorageSqlPath);
171
    }
172
173
    /**
174
     * @param Composer\Script\Event $event
175
     * @param $rootDir
176
     * @param $dirName
177
     * @return string
178
     */
179
    private static function createDir($event, $rootDir, $dirName)
180
    {
181
        $dir = $rootDir . DIRECTORY_SEPARATOR . $dirName . DIRECTORY_SEPARATOR;
182
        if (!is_dir($dir)) {
183
            if (!mkdir($dir) && !is_dir($dir)) {
184
                throw new \RuntimeException(sprintf('Directory "%s" was not created', $dir));
185
            }
186
            $event->getIO()->write("[INSTALL] Created dir: " . $dir);
187
        } else {
188
            $event->getIO()->write("[INFO] Dir already exists: " . $dir);
189
        }
190
        return self::getRelativePath($rootDir, $dir);
191
    }
192
193
    /**
194
     * @param Composer\Script\Event $event
195
     * @param $configTargetPath
196
     * @return mixed
197
     */
198
    private static function getConfig($event, $configTargetPath)
199
    {
200
        $baseConfigDefaultPath = realpath(__DIR__ . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR . '_config.json');
201
202
        if (file_exists($configTargetPath)) {
203
            $config = json_decode(file_get_contents($configTargetPath));
204
            $event->getIO()->write("[INFO] Using existing config");
205
        } else {
206
            $config = json_decode(file_get_contents($baseConfigDefaultPath));
207
            $event->getIO()->write("[INSTALL] Created default config");
208
        }
209
        return $config;
210
    }
211
212
    /**
213
     * Calculate the relative path from $from to $to
214
     * Derived from https://stackoverflow.com/a/2638272/
215
     *
216
     * @param $from
217
     * @param $to
218
     * @return string
219
     */
220
    private static function getRelativePath($from, $to)
221
    {
222
        // some compatibility fixes for Windows paths
223
        $from = is_dir($from) ? rtrim($from, '\/') . DIRECTORY_SEPARATOR : $from;
224
        $to = is_dir($to) ? rtrim($to, '\/') . DIRECTORY_SEPARATOR : $to;
225
        $from = str_replace('\\', DIRECTORY_SEPARATOR, $from);
226
        $to = str_replace('\\', DIRECTORY_SEPARATOR, $to);
227
228
        $from = explode(DIRECTORY_SEPARATOR, $from);
229
        $to = explode(DIRECTORY_SEPARATOR, $to);
230
        $relPath = $to;
231
232
        $relPath = self::calculateRelativePath($from, $to, $relPath);
233
        $relPath = implode(DIRECTORY_SEPARATOR, $relPath);
234
        $relPath = self::removePointerToCurrentDir($relPath);
235
        return $relPath;
236
    }
237
238
    /**
239
     * @param $relPath
240
     * @return mixed
241
     */
242
    private static function removePointerToCurrentDir($relPath)
243
    {
244
        while (strpos($relPath, '.' . DIRECTORY_SEPARATOR . '.' . DIRECTORY_SEPARATOR) !== false) {
245
            $relPath = str_replace('.' . DIRECTORY_SEPARATOR . '.' . DIRECTORY_SEPARATOR, '.' . DIRECTORY_SEPARATOR, $relPath);
246
        }
247
        return $relPath;
248
    }
249
250
    /**
251
     * @param $from
252
     * @param $to
253
     * @param $relPath
254
     * @return array
255
     */
256
    private static function calculateRelativePath($from, $to, $relPath)
257
    {
258
        foreach ($from as $depth => $dir) {
259
            // find first non-matching dir
260
            if ($dir === $to[$depth]) {
261
                // ignore this directory
262
                array_shift($relPath);
263
            } else {
264
                // get number of remaining dirs to $from
265
                $remaining = count($from) - $depth;
266
                if ($remaining > 1) {
267
                    // add traversals up to first matching dir
268
                    $padLength = (count($relPath) + $remaining - 1) * -1;
269
                    $relPath = array_pad($relPath, $padLength, '..');
270
                    break;
271
                } else {
272
                    $relPath[0] = '.' . DIRECTORY_SEPARATOR . $relPath[0];
273
                }
274
            }
275
        }
276
        return $relPath;
277
    }
278
279
    private static function createCacheStorage($storageDir, $baseCacheSqlPath)
280
    {
281
        Cache::getInstance()->setStoragePath($storageDir);
282
        Cache::getInstance()->init($baseCacheSqlPath);
283
    }
284
285
    /**
286
     * ini settings
287
     */
288
    private static function iniSets()
289
    {
290
        // Error settings
291
        ini_set('display_errors', true);
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $newvalue of ini_set(). ( Ignorable by Annotation )

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

291
        ini_set('display_errors', /** @scrutinizer ignore-type */ true);
Loading history...
292
        ini_set('error_reporting', E_ALL);
293
294
        // Allow Short Open Tags
295
        ini_set('short_open_tag', true);
296
    }
297
298
    /**
299
     * Set internal encoding
300
     */
301
    private static function setInternalEncoding()
302
    {
303
        if (function_exists('mb_internal_encoding')) {
304
            mb_internal_encoding('UTF-8');
305
        }
306
    }
307
308
    /**
309
     * Time settings
310
     */
311
    private static function setLocalisation()
312
    {
313
        setlocale(LC_ALL, 'nl_NL');
314
        date_default_timezone_set('Europe/Amsterdam');
315
    }
316
317
}