Passed
Push — master ( cf7c5c...d67f1e )
by Matthew
07:04
created

command_functions.php ➔ getVendorDir()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 9

Duplication

Lines 18
Ratio 100 %

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 4
nop 1
dl 18
loc 18
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @param  string $current_dir
5
 * @param  bool   $has_explicit_root
6
 * @param  string $vendor_dir
7
 *
8
 * @return void
9
 */
10
function requireAutoloaders($current_dir, $has_explicit_root, $vendor_dir)
11
{
12
    $autoload_roots = [$current_dir];
13
14
    $psalm_dir = dirname(__DIR__);
15
16
    if (realpath($psalm_dir) !== realpath($current_dir)) {
17
        $autoload_roots[] = $psalm_dir;
18
    }
19
20
    $autoload_files = [];
21
22
    foreach ($autoload_roots as $autoload_root) {
23
        $has_autoloader = false;
24
25
        $nested_autoload_file = dirname(dirname($autoload_root)) . DIRECTORY_SEPARATOR . 'autoload.php';
26
27
        if (file_exists($nested_autoload_file)) {
28
            $autoload_files[] = realpath($nested_autoload_file);
29
            $has_autoloader = true;
30
        }
31
32
        $vendor_autoload_file = $autoload_root . DIRECTORY_SEPARATOR . $vendor_dir . DIRECTORY_SEPARATOR . 'autoload.php';
33
34
        if (file_exists($vendor_autoload_file)) {
35
            $autoload_files[] = realpath($vendor_autoload_file);
36
            $has_autoloader = true;
37
        }
38
39
        if (!$has_autoloader) {
40
            $error_message = 'Could not find any composer autoloaders in ' . $autoload_root;
41
42
            if (!$has_explicit_root) {
43
                $error_message .= PHP_EOL . 'Add a --root=[your/project/directory] flag '
44
                    . 'to specify a particular project to run Psalm on.';
45
            }
46
47
            die($error_message . PHP_EOL);
0 ignored issues
show
Coding Style Compatibility introduced by
The function requireAutoloaders() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
48
        }
49
    }
50
51
    foreach ($autoload_files as $file) {
52
        /** @psalm-suppress UnresolvableInclude */
53
        require_once $file;
54
    }
55
}
56
57
/**
58
 * @param  string $current_dir
59
 *
60
 * @return string
61
 *
62
 * @psalm-suppress PossiblyFalseArgument
63
 * @psalm-suppress MixedArrayAccess
64
 * @psalm-suppress MixedAssignment
65
 */
66 View Code Duplication
function getVendorDir($current_dir)
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
67
{
68
    $composer_json_path = $current_dir . DIRECTORY_SEPARATOR . 'composer.json'; // this should ideally not be hardcoded
69
70
    if (!file_exists($composer_json_path)) {
71
        return 'vendor';
72
    }
73
74
    if (!$composer_json = json_decode(file_get_contents($composer_json_path), true)) {
75
        throw new \UnexpectedValueException('Invalid composer.json at ' . $composer_json_path);
76
    }
77
78
    if (isset($composer_json['config']['vendor-dir'])) {
79
         return (string) $composer_json['config']['vendor-dir'];
80
    }
81
82
    return 'vendor';
83
}
84
85
/**
86
 * @param  string|array|null|false $f_paths
87
 *
88
 * @return string[]|null
89
 */
90
function getPathsToCheck($f_paths)
91
{
92
    global $argv;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
93
94
    $paths_to_check = [];
95
96
    if ($f_paths) {
97
        $input_paths = is_array($f_paths) ? $f_paths : [$f_paths];
98
    } else {
99
        $input_paths = $argv ? $argv : null;
100
    }
101
102
    if ($input_paths) {
103
        $filtered_input_paths = [];
104
105
        for ($i = 0; $i < count($input_paths); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
106
            /** @var string */
107
            $input_path = $input_paths[$i];
108
109
            if (realpath($input_path) === realpath(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'psalm')
110
                || realpath($input_path) === realpath(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'psalter')
111
            ) {
112
                continue;
113
            }
114
115
            if ($input_path[0] === '-' && strlen($input_path) === 2) {
116
                if ($input_path[1] === 'c' || $input_path[1] === 'f') {
117
                    ++$i;
118
                }
119
                continue;
120
            }
121
122
            if ($input_path[0] === '-' && $input_path[2] === '=') {
123
                continue;
124
            }
125
126
            if (substr($input_path, 0, 2) === '--' && strlen($input_path) > 2) {
127
                continue;
128
            }
129
130
            $filtered_input_paths[] = $input_path;
131
        }
132
133
        if ($filtered_input_paths === ['-']) {
134
            $meta = stream_get_meta_data(STDIN);
135
            stream_set_blocking(STDIN, false);
136
            if ($stdin = fgets(STDIN)) {
137
                $filtered_input_paths = preg_split('/\s+/', trim($stdin));
138
            }
139
            /** @var bool */
140
            $blocked = $meta['blocked'];
141
            stream_set_blocking(STDIN, $blocked);
142
        }
143
144
        foreach ($filtered_input_paths as $i => $path_to_check) {
145
            if ($path_to_check[0] === '-') {
146
                die('Invalid usage, expecting psalm [options] [file...]' . PHP_EOL);
0 ignored issues
show
Coding Style Compatibility introduced by
The function getPathsToCheck() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
147
            }
148
149
            if (!file_exists($path_to_check)) {
150
                die('Cannot locate ' . $path_to_check . PHP_EOL);
0 ignored issues
show
Coding Style Compatibility introduced by
The function getPathsToCheck() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
151
            }
152
153
            $path_to_check = realpath($path_to_check);
154
155
            if (!$path_to_check) {
156
                die('Error getting realpath for file' . PHP_EOL);
0 ignored issues
show
Coding Style Compatibility introduced by
The function getPathsToCheck() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
157
            }
158
159
            $paths_to_check[] = $path_to_check;
160
        }
161
162
        if (!$paths_to_check) {
1 ignored issue
show
Bug Best Practice introduced by
The expression $paths_to_check of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
163
            $paths_to_check = null;
164
        }
165
    }
166
167
    return $paths_to_check;
168
}
169