Completed
Branch 4.0 (52c68b)
by Marc André
02:54
created

Tools::phpstormMetadataHeader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 2 Features 0
Metric Value
c 4
b 2
f 0
dl 0
loc 11
rs 9.4285
cc 1
eloc 4
nc 1
nop 0
1
<?php
2
3
4
/**
5
 *
6
 * Copyright (c) 2010-2016 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
class Tools
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
     * \CervoTools::phpstormMetadata()
55
     *
56
     * @param string|null $json_config_file The path to the JSON configuration file to use.
57
     */
58
    public static function phpstormMetadata($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'), $config->get('Cervo/Application/LibariesPath'))) .
73
            self::phpstormMetadataControllers(self::getApplicationClasses($config->get('Cervo/Application/Directory'), $config->get('Cervo/Application/ControllersPath'))) .
74
            self::phpstormMetadataModels(self::getApplicationClasses($config->get('Cervo/Application/Directory'), $config->get('Cervo/Application/ModelsPath'))) .
75
            self::phpstormMetadataViews(self::getApplicationClasses($config->get('Cervo/Application/Directory'), $config->get('Cervo/Application/ViewsPath'))) .
76
            self::phpstormMetadataFooter()
77
        );
78
79
        echo '</pre>';
80
    }
81
82
    /**
83
     * Fetch a list of all the Cervo Libraries class.
84
     *
85
     * @param string $path The path to the Cervo Libraries folder
86
     *
87
     * @return array
88
     */
89
    private static function getCervoLibraries($path)
90
    {
91
        $len = strlen($path);
92
93
        $files = self::globRecursive([$path]);
94
        $classes = [];
95
96
        foreach ($files as $file) {
97
            if (strncmp($path, $file, $len) === 0 && substr($file, -4) === '.php') {
98
                $class = str_replace('\\', '/', substr($file, $len, -4));
99
100
                if (strpos($class, 'Exceptions/') !== 0) {
101
                    $classes[] = $class;
102
                }
103
            }
104
        }
105
106
        return $classes;
107
    }
108
109
    /**
110
     * Fetch a list of all the Application classes depending on the sub path.
111
     *
112
     * @param string $path The path to the Application root
113
     * @param string $sub_path The sub-path to look for
114
     *
115
     * @return array
116
     */
117
    private static function getApplicationClasses($path, $sub_path)
118
    {
119
        $files = self::globRecursive(glob($path . '*' . \DS . $sub_path, GLOB_ONLYDIR));
120
        $path_len = strlen($path);
121
        $classes = [];
122
123
        foreach ($files as $file) {
124
125
            if (strncmp($path, $file, $path_len) === 0 && substr($file, -4) === '.php') {
126
127
                $cur = str_replace('\\', '/', str_replace(\DS . $sub_path, '/', substr($file, $path_len, -4)));
128
                $ex = explode('/', $cur);
129
130
                if (count($ex) === 2 && $ex[0] === $ex[1]) {
131
                    $cur = $ex[0];
132
                }
133
134
                $classes[] = $cur;
135
136
            }
137
138
        }
139
140
        return $classes;
141
    }
142
143
    private static function phpstormMetadataHeader()
144
    {
145
        return <<<METADATA
146
<?php
147
148
namespace PHPSTORM_META
149
{
150
    \$STATIC_METHOD_TYPES = [
151
152
METADATA;
153
    }
154
155
    private static function phpstormMetadataLibraries($cervo_libraries, $libraries)
156
    {
157
        $towrite = <<<METADATA
158
        \Cervo\Core::getLibrary('') => [
159
160
METADATA;
161
162
        foreach ($cervo_libraries as $f) {
163
            $class = str_replace('/', '\\', $f);
164
165
            $towrite .= '            \'Cervo/' . $f . '\' instanceof \Cervo\Libraries\\' . $class . ",\n";
166
        }
167
168
        foreach ($libraries as $f) {
169
            $ex = explode('/', $f);
170
171
            if (count($ex) <= 1) {
172
                $towrite .= '            \'' . $ex[0] . '\' instanceof \Application\\' . $ex[0] . 'Module\Libraries\\' . $ex[0] . ",\n";
173
                $towrite .= '            \'' . $ex[0] . '/' . $ex[0] . '\' instanceof \Application\\' . $ex[0] . 'Module\Libraries\\' . $ex[0] . ",\n";
174 View Code Duplication
            } else {
175
                $towrite .= '            \'' . $f . '\' instanceof \Application\\' . $ex[0] . 'Module\Libraries\\' . implode('\\', array_slice($ex, 1)) . ",\n";
176
            }
177
        }
178
179
        $towrite .= <<<METADATA
180
        ],
181
182
METADATA;
183
184
        return $towrite;
185
    }
186
187
    private static function phpStormMetadataGenerator($function_call, $classes, $namespace)
188
    {
189
        $towrite = <<<METADATA
190
        \Cervo\Core::{$function_call}('') => [
191
192
METADATA;
193
194
        foreach ($classes as $f) {
195
            $ex = explode('/', $f);
196
197
            if (count($ex) <= 1) {
198
                $towrite .= '            \'' . $ex[0] . '\' instanceof \Application\\' . $ex[0] . 'Module\\' . $namespace . '\\' . $ex[0] . ",\n";
199
                $towrite .= '            \'' . $ex[0] . '/' . $ex[0] . '\' instanceof \Application\\' . $ex[0] . 'Module\\' . $namespace . '\\' . $ex[0] . ",\n";
200 View Code Duplication
            } else {
201
                $towrite .= '            \'' . $f . '\' instanceof \Application\\' . $ex[0] . 'Module\\' . $namespace . '\\' . implode('\\', array_slice($ex, 1)) . ",\n";
202
            }
203
        }
204
205
        $towrite .= <<<METADATA
206
        ],
207
208
METADATA;
209
210
        return $towrite;
211
    }
212
213
    private static function phpstormMetadataControllers($controllers)
214
    {
215
        return self::phpStormMetadataGenerator('getController', $controllers, 'Controllers');
216
    }
217
218
    private static function phpstormMetadataModels($models)
219
    {
220
        return self::phpStormMetadataGenerator('getModel', $models, 'Models');
221
    }
222
223
    private static function phpstormMetadataViews($views)
224
    {
225
        return self::phpStormMetadataGenerator('getView', $views, 'Views');
226
    }
227
228
    private static function phpstormMetadataFooter()
229
    {
230
        return <<<METADATA
231
232
    ];
233
}
234
235
METADATA;
236
    }
237
238
    /**
239
     * Recursively return every files under the $folders array.
240
     * Does not accept a string.
241
     *
242
     * Returns a list of all the files under the folders.
243
     *
244
     * @param array $folders List of folders to scan from
245
     *
246
     * @return array
247
     */
248
    private static function globRecursive(array $folders)
249
    {
250
        $files = [];
251
252
        while (count($folders) > 0) {
253
254
            $cur = array_pop($folders);
255
256
            foreach (glob($cur . '*', GLOB_MARK) as $file) {
257
258
                if (is_dir($file)) {
259
                    array_push($folders, $file);
260
                } else if (is_file($file) && is_readable($file)) {
261
                    $files[] = $file;
262
                }
263
264
            }
265
266
        }
267
268
        return $files;
269
    }
270
}
271