Completed
Push — 4.0 ( bb82bd...2eee71 )
by Marc André
02:22
created

PhpStormMetadata::getApplicationClasses()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 25
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 25
rs 8.439
cc 6
eloc 12
nc 4
nop 2
1
<?php
2
3
4
/**
5
 *
6
 * Copyright (c) 2010-2017 Nevraxe inc. & Marc André Audet <[email protected]>. All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without modification, are
9
 * permitted provided that the following conditions are met:
10
 *
11
 *   1. Redistributions of source code must retain the above copyright notice, this list of
12
 *       conditions and the following disclaimer.
13
 *
14
 *   2. Redistributions in binary form must reproduce the above copyright notice, this list
15
 *       of conditions and the following disclaimer in the documentation and/or other materials
16
 *       provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 */
30
31
32
namespace Cervo;
33
34
35
use Cervo\Core as _;
36
37
38
/**
39
 * Tools for Cervo.
40
 *
41
 * @author Marc André Audet <[email protected]>
42
 */
43
final class PhpStormMetadata
44
{
45
    /**
46
     * Generates the content to put in a metadata file for PHPStorm.
47
     * It does not scan the content of the files, so it makes no difference
48
     * between an abstract class or a regular class. It have been written
49
     * in a way that it gives more results then should be used, but it
50
     * should cover every classes for every calls.
51
     *
52
     * To use this, in your index.php file (Or your file that calls
53
     * \Cervo::init()) you simply need to replace the init() call with
54
     * \PhpStormMetadata::generate()
55
     *
56
     * @param string|null $json_config_file The path to the JSON configuration file to use.
57
     */
58
    public static function generate($json_config_file = null)
59
    {
60
        // Start the configuration process
61
62
        _::initConfig($json_config_file);
63
        $config = _::getLibrary('Cervo/Config');
64
65
66
        // Print out the results
67
68
        echo '<pre>';
69
70
        echo htmlentities(
71
            self::phpstormMetadataHeader() .
72
            self::phpstormMetadataLibraries(self::getCervoLibraries($config->get('Cervo/Libraries/Directory')), self::getApplicationClasses($config->get('Cervo/Application/Directory'), 'Libraries')) .
73
            self::phpstormMetadataControllers(self::getApplicationClasses($config->get('Cervo/Application/Directory'), 'Controllers')) .
74
            self::phpstormMetadataFooter()
75
        );
76
77
        echo '</pre>';
78
    }
79
80
    /**
81
     * Fetch a list of all the Cervo Libraries class.
82
     *
83
     * @param string $path The path to the Cervo Libraries folder
84
     *
85
     * @return array
86
     */
87
    private static function getCervoLibraries($path)
88
    {
89
        $len = strlen($path);
90
91
        $files = self::globRecursive([$path]);
92
        $classes = [];
93
94
        foreach ($files as $file) {
95
            if (strncmp($path, $file, $len) === 0 && substr($file, -4) === '.php') {
96
                $class = str_replace('\\', '/', substr($file, $len, -4));
97
98
                if (strpos($class, 'Exceptions/') !== 0) {
99
                    $classes[] = $class;
100
                }
101
            }
102
        }
103
104
        return $classes;
105
    }
106
107
    /**
108
     * Fetch a list of all the Application classes depending on the sub path.
109
     *
110
     * @param string $path The path to the Application root
111
     * @param string $sub_path The sub-path to look for
112
     *
113
     * @return array
114
     */
115
    private static function getApplicationClasses($path, $sub_path)
116
    {
117
        $files = self::globRecursive(glob($path . '*' . \DS . $sub_path, GLOB_ONLYDIR));
118
        $path_len = strlen($path);
119
        $classes = [];
120
121
        foreach ($files as $file) {
122
123
            if (strncmp($path, $file, $path_len) === 0 && substr($file, -4) === '.php') {
124
125
                $cur = str_replace('\\', '/', str_replace(\DS . $sub_path, '/', substr($file, $path_len, -4)));
126
                $ex = explode('/', $cur);
127
128
                if (count($ex) === 2 && $ex[0] === $ex[1]) {
129
                    $cur = $ex[0];
130
                }
131
132
                $classes[] = $cur;
133
134
            }
135
136
        }
137
138
        return $classes;
139
    }
140
141
    private static function phpstormMetadataHeader()
142
    {
143
        return <<<METADATA
144
<?php
145
146
namespace PHPSTORM_META
147
{
148
    \$STATIC_METHOD_TYPES = [
149
150
METADATA;
151
    }
152
153
    private static function phpstormMetadataLibraries($cervo_libraries, $libraries)
154
    {
155
        $towrite = <<<METADATA
156
        \Cervo\Core::getLibrary('') => [
157
158
METADATA;
159
160
        foreach ($cervo_libraries as $f) {
161
            $class = str_replace('/', '\\', $f);
162
163
            $towrite .= '            \'Cervo/' . $f . '\' instanceof \Cervo\Libraries\\' . $class . ",\n";
164
        }
165
166 View Code Duplication
        foreach ($libraries as $f) {
167
            $ex = explode('/', $f);
168
169
            if (count($ex) <= 1) {
170
                $towrite .= '            \'' . $ex[0] . '\' instanceof \Application\\' . $ex[0] . 'Module\Libraries\\' . $ex[0] . ",\n";
171
                $towrite .= '            \'' . $ex[0] . '/' . $ex[0] . '\' instanceof \Application\\' . $ex[0] . 'Module\Libraries\\' . $ex[0] . ",\n";
172
            } else {
173
                $towrite .= '            \'' . $f . '\' instanceof \Application\\' . $ex[0] . 'Module\Libraries\\' . implode('\\', array_slice($ex, 1)) . ",\n";
174
            }
175
        }
176
177
        foreach (_::getInjectedLibraries() as $name => $i_name) {
178
            $towrite .= '            \'' . $name . '\' instanceof ' . $i_name . ",\n";
179
        }
180
181
        $towrite .= <<<METADATA
182
        ],
183
184
METADATA;
185
186
        return $towrite;
187
    }
188
189
    private static function phpstormMetadataControllers($controllers)
190
    {
191
        $towrite = <<<METADATA
192
        \Cervo\Core::getController('') => [
193
194
METADATA;
195
196 View Code Duplication
        foreach ($controllers as $f) {
197
            $ex = explode('/', $f);
198
199
            if (count($ex) <= 1) {
200
                $towrite .= '            \'' . $ex[0] . '\' instanceof \Application\\' . $ex[0] . 'Module\\Controllers\\' . $ex[0] . ",\n";
201
                $towrite .= '            \'' . $ex[0] . '/' . $ex[0] . '\' instanceof \Application\\' . $ex[0] . 'Module\\Controllers\\' . $ex[0] . ",\n";
202
            } else {
203
                $towrite .= '            \'' . $f . '\' instanceof \Application\\' . $ex[0] . 'Module\\Controllers\\' . implode('\\', array_slice($ex, 1)) . ",\n";
204
            }
205
        }
206
207
        foreach (_::getInjectedControllers() as $name => $i_name) {
208
            $towrite .= '            \'' . $name . '\' instanceof ' . $i_name . ",\n";
209
        }
210
211
        $towrite .= <<<METADATA
212
        ],
213
214
METADATA;
215
216
        return $towrite;
217
    }
218
219
    private static function phpstormMetadataFooter()
220
    {
221
        return <<<METADATA
222
223
    ];
224
}
225
226
METADATA;
227
    }
228
229
    /**
230
     * Recursively return every files under the $folders array.
231
     * Does not accept a string.
232
     *
233
     * Returns a list of all the files under the folders.
234
     *
235
     * @param array $folders List of folders to scan from
236
     *
237
     * @return array
238
     */
239
    private static function globRecursive(array $folders)
240
    {
241
        $files = [];
242
243
        while (count($folders) > 0) {
244
245
            $cur = array_pop($folders);
246
247
            foreach (glob($cur . '*', GLOB_MARK) as $file) {
248
249
                if (is_dir($file)) {
250
                    array_push($folders, $file);
251
                } else if (is_file($file) && is_readable($file)) {
252
                    $files[] = $file;
253
                }
254
255
            }
256
257
        }
258
259
        return $files;
260
    }
261
}
262