Passed
Push — develop ( f63f67...7af1af )
by Jens
04:23
created

ComposerScripts::copyAndOverwriteInstallFile()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
c 0
b 0
f 0
nc 4
nop 4
dl 0
loc 9
rs 9.6666
1
<?php
2
/**
3
 * Created by jensk on 27-3-2018.
4
 */
5
6
namespace CloudControl\Cms\cc;
7
8
use CloudControl\Cms\storage\Cache;
9
use CloudControl\Cms\storage\Repository;
10
use Composer\Script\Event;
11
12
class ComposerScripts
13
{
14
    /**
15
     * @param Event $event
16
     * @throws \Exception
17
     */
18
    public static function postInstall($event)
19
    {
20
        $event->getIO()->write("Post install");
21
        self::checkInstall($event);
22
    }
23
24
    /**
25
     * @param Event $event
26
     * @throws \Exception
27
     */
28
    public static function postUpdate($event)
29
    {
30
        $event->getIO()->write("Post update");
31
        self::checkInstall($event);
32
    }
33
34
    /**
35
     * @param Event $event
36
     * @throws \Exception
37
     */
38
    public static function checkInstall($event)
39
    {
40
        $event->getIO()->write('');
41
        $event->getIO()->write('********************************************************');
42
        $event->getIO()->write('*** Checking installation of Cloud Control framework ***');
43
        $event->getIO()->write('********************************************************');
44
        $event->getIO()->write('');
45
46
        $vendorDir = $event->getComposer()->getConfig()->get('vendor-dir');
47
        $rootDir = realpath($vendorDir . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR);
48
49
        $baseConfigTargetPath = $rootDir . DIRECTORY_SEPARATOR . 'config.json';
50
        $configObject = self::getConfig($event, $baseConfigTargetPath);
51
52
        $configObject->{'templateDir'} = self::createDir($event, $rootDir, 'templates');
53
        $configObject->{'storageDir'} = self::createDir($event, $rootDir, $configObject->{'storageDir'});
54
        $configObject->{'publicDir'} = self::createDir($event, $rootDir, 'public');
55
        $configObject->{'jsDir'} = self::createDir($event, $rootDir, $configObject->{'publicDir'} . 'js');
56
        $configObject->{'cssDir'} = self::createDir($event, $rootDir, $configObject->{'publicDir'} . 'css');
57
        $configObject->{'imagesDir'} = self::createDir($event, $rootDir, $configObject->{'publicDir'} . 'images');
58
        $configObject->{'filesDir'} = self::createDir($event, $rootDir, $configObject->{'publicDir'} . 'files');
59
        $componentsDir = self::createDir($event, $rootDir, 'components');
60
61
        $baseStorageDefaultPath = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR . '_storage.json';
62
        $baseStorageSqlPath = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR . '_storage.sql';
63
        $baseCacheSqlPath = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR . '_cache.sql';
64
65
        self::createStorage($configObject->{'storageDir'}, $baseStorageDefaultPath, $baseStorageSqlPath);
66
        self::createCacheStorage($rootDir . DIRECTORY_SEPARATOR . $configObject->{'storageDir'}, $baseCacheSqlPath);
67
        self::saveConfig($event, $baseConfigTargetPath, $configObject);
68
        self::copyInstallFile($event, 'public.htaccess', $configObject->{'publicDir'}, '.htaccess');
69
        self::copyInstallFile($event, 'root.htaccess', $rootDir, '.htaccess');
70
        self::copyInstallFile($event, 'base.php', $configObject->{'templateDir'});
71
        self::copyAndOverwriteInstallFile($event, 'cms.css', $configObject->{'cssDir'});
72
        self::copyAndOverwriteInstallFile($event, 'cms.js', $configObject->{'jsDir'});
73
        self::copyInstallFile($event, 'index.php', $configObject->{'publicDir'});
74
        self::copyInstallFile($event, 'CustomComponent.php', $componentsDir);
75
76
        $event->getIO()->write("");
77
        $event->getIO()->write("[SUCCESS] Installation is complete");
78
        $event->getIO()->write("");
79
    }
80
81
    /**
82
     * @param Event $event
83
     * @param $baseConfigTargetPath
84
     * @param $configObject
85
     */
86
    private static function saveConfig($event, $baseConfigTargetPath, $configObject)
87
    {
88
        file_put_contents($baseConfigTargetPath, json_encode($configObject));
89
        $event->getIO()->write("[INFO] Saved config to: " . $baseConfigTargetPath);
90
    }
91
92
    private static function copyAndOverwriteInstallFile($event, $sourceFileName, $destinationPath, $destinationFileName = null) {
93
        if ($destinationFileName === null) {
94
            $destinationFileName = $sourceFileName;
95
        }
96
        $destinationFullPath = realpath($destinationPath) . DIRECTORY_SEPARATOR . $destinationFileName;
97
        if (file_exists($destinationFullPath)) {
98
            unlink($destinationFullPath);
99
        }
100
        self::copyInstallFile($event, $sourceFileName, $destinationPath, $destinationFileName);
101
    }
102
103
    /**
104
     * @param Event $event
105
     * @param $sourceFileName
106
     * @param $destinationPath
107
     * @param string $destinationFileName
108
     */
109
    private static function copyInstallFile($event, $sourceFileName, $destinationPath, $destinationFileName = null)
110
    {
111
        $sourceFilePath = realpath(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'install/_' . $sourceFileName);
112
113
114
        if ($destinationFileName === null) {
115
            $destinationFileName = $sourceFileName;
116
        }
117
118
        if (file_exists($sourceFilePath) && realpath($destinationPath) !== false) {
119
            $destinationFullPath = realpath($destinationPath) . DIRECTORY_SEPARATOR . $destinationFileName;
120
            if (file_exists($destinationFullPath)) {
121
                $event->getIO()->write("[INFO] File already exists: " . $destinationFullPath);
122
            } else {
123
                copy($sourceFilePath, $destinationFullPath);
124
                $event->getIO()->write("[INSTALL] Copied file: " . $sourceFileName . ' to ' . $destinationPath);
125
            }
126
        } else {
127
            $event->getIO()->write("[ERROR] Couldnt copy file: " . $sourceFileName . ' to ' . $destinationPath);
128
        }
129
    }
130
131
    /**
132
     * @param $storageDir
133
     * @param $baseStorageDefaultPath
134
     * @param $baseStorageSqlPath
135
     * @throws \Exception
136
     */
137
    private static function createStorage($storageDir, $baseStorageDefaultPath, $baseStorageSqlPath)
138
    {
139
        $repository = new Repository($storageDir);
140
        $repository->init($baseStorageDefaultPath, $baseStorageSqlPath);
141
    }
142
143
    /**
144
     * @param Event $event
145
     * @param $rootDir
146
     * @param $dirName
147
     * @return string
148
     */
149
    private static function createDir($event, $rootDir, $dirName)
150
    {
151
        $dir = $rootDir . DIRECTORY_SEPARATOR . $dirName . DIRECTORY_SEPARATOR;
152
        if (!is_dir($dir)) {
153
            if (!mkdir($dir) && !is_dir($dir)) {
154
                throw new \RuntimeException(sprintf('Directory "%s" was not created', $dir));
155
            }
156
            $event->getIO()->write("[INSTALL] Created dir: " . $dir);
157
        } else {
158
            $event->getIO()->write("[INFO] Dir already exists: " . $dir);
159
        }
160
        return self::getRelativePath($rootDir, $dir);
161
    }
162
163
    /**
164
     * @param Event $event
165
     * @param $configTargetPath
166
     * @return mixed
167
     */
168
    private static function getConfig($event, $configTargetPath)
169
    {
170
        $baseConfigDefaultPath = realpath(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR . '_config.json');
171
172
        if (file_exists($configTargetPath)) {
173
            $config = json_decode(file_get_contents($configTargetPath));
174
            $event->getIO()->write("[INFO] Using existing config");
175
        } else {
176
            $config = json_decode(file_get_contents($baseConfigDefaultPath));
177
            $event->getIO()->write("[INSTALL] Created default config");
178
        }
179
        return $config;
180
    }
181
182
    /**
183
     * @param $storageDir
184
     * @param $baseCacheSqlPath
185
     */
186
    private static function createCacheStorage($storageDir, $baseCacheSqlPath)
187
    {
188
        Cache::getInstance()->setStoragePath($storageDir);
189
        Cache::getInstance()->init($baseCacheSqlPath);
190
    }
191
192
    /**
193
     * Calculate the relative path from $from to $to
194
     * Derived from https://stackoverflow.com/a/2638272/
195
     *
196
     * @param $from
197
     * @param $to
198
     * @return string
199
     */
200
    private static function getRelativePath($from, $to)
201
    {
202
        // some compatibility fixes for Windows paths
203
        $from = is_dir($from) ? rtrim($from, '\/') . DIRECTORY_SEPARATOR : $from;
204
        $to = is_dir($to) ? rtrim($to, '\/') . DIRECTORY_SEPARATOR : $to;
205
        $from = str_replace('\\', DIRECTORY_SEPARATOR, $from);
206
        $to = str_replace('\\', DIRECTORY_SEPARATOR, $to);
207
208
        $from = explode(DIRECTORY_SEPARATOR, $from);
209
        $to = explode(DIRECTORY_SEPARATOR, $to);
210
        $relPath = $to;
211
212
        $relPath = self::calculateRelativePath($from, $to, $relPath);
213
        $relPath = implode(DIRECTORY_SEPARATOR, $relPath);
214
        $relPath = self::removePointerToCurrentDir($relPath);
215
        return $relPath;
216
    }
217
218
    /**
219
     * @param $relPath
220
     * @return mixed
221
     */
222
    private static function removePointerToCurrentDir($relPath)
223
    {
224
        while (strpos($relPath, '.' . DIRECTORY_SEPARATOR . '.' . DIRECTORY_SEPARATOR) !== false) {
225
            $relPath = str_replace('.' . DIRECTORY_SEPARATOR . '.' . DIRECTORY_SEPARATOR, '.' . DIRECTORY_SEPARATOR,
226
                $relPath);
227
        }
228
        return $relPath;
229
    }
230
231
    /**
232
     * @param $from
233
     * @param $to
234
     * @param $relPath
235
     * @return array
236
     */
237
    private static function calculateRelativePath($from, $to, $relPath)
238
    {
239
        foreach ($from as $depth => $dir) {
240
            // find first non-matching dir
241
            if ($dir === $to[$depth]) {
242
                // ignore this directory
243
                array_shift($relPath);
244
            } else {
245
                // get number of remaining dirs to $from
246
                $remaining = count($from) - $depth;
247
                if ($remaining > 1) {
248
                    // add traversals up to first matching dir
249
                    $padLength = (count($relPath) + $remaining - 1) * -1;
250
                    $relPath = array_pad($relPath, $padLength, '..');
251
                    break;
252
                } else {
253
                    $relPath[0] = '.' . DIRECTORY_SEPARATOR . $relPath[0];
254
                }
255
            }
256
        }
257
        return $relPath;
258
    }
259
}