Passed
Branch develop (96efe9)
by Jens
02:38
created

CloudControl::getRelativePath()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

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