Completed
Push — develop ( 8eb671...133594 )
by Mike
19:30 queued 09:24
created

src/phpDocumentor/Descriptor/Example/Finder.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * This file is part of phpDocumentor.
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @author    Mike van Riel <[email protected]>
11
 * @copyright 2010-2018 Mike van Riel / Naenius (http://www.naenius.com)
12
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
13
 * @link      http://phpdoc.org
14
 */
15
16
namespace phpDocumentor\Descriptor\Example;
17
18
use phpDocumentor\Descriptor\Tag\ExampleDescriptor;
19
20
/**
21
 * Class used to find an example file's location based on a given ExampleDescriptor.
22
 */
23
class Finder
24
{
25
    /** @var string */
26
    private $sourceDirectory = '';
27
28
    /** @var string[] */
29
    private $exampleDirectories = [];
30
31
    /**
32
     * Attempts to find the example contents for the given descriptor.
33
     */
34 5
    public function find(ExampleDescriptor $descriptor): string
35
    {
36 5
        $filename = $descriptor->getFilePath();
37
38 5
        $file = $this->getExampleFileContents($filename);
39 5
        if (! $file) {
40 1
            return "** File not found : {$filename} **";
41
        }
42
43 4
        return implode('', array_slice($file, $descriptor->getStartingLine() - 1, $descriptor->getLineCount()));
44
    }
45
46
    /**
47
     * Registers the project's root directory where an 'examples' folder can be expected.
48
     */
49 1
    public function setSourceDirectory(string $directory = ''): void
50
    {
51 1
        $this->sourceDirectory = $directory;
52 1
    }
53
54
    /**
55
     * Returns the project's root directory where an 'examples' folder can be expected.
56
     */
57 1
    public function getSourceDirectory(): string
58
    {
59 1
        return $this->sourceDirectory;
60
    }
61
62
    /**
63
     * Registers a series of directories that may contain examples.
64
     *
65
     * @param string[] $directories
66
     */
67 1
    public function setExampleDirectories(array $directories = []): void
68
    {
69 1
        $this->exampleDirectories = $directories;
70 1
    }
71
72
    /**
73
     * Returns a series of directories that may contain examples.
74
     *
75
     * @return string[]
76
     */
77 1
    public function getExampleDirectories(): array
78
    {
79 1
        return $this->exampleDirectories;
80
    }
81
82
    /**
83
     * Attempts to find the requested example file and returns its contents or null if no file was found.
84
     *
85
     * This method will try several methods in search of the given example file, the first one it encounters is
86
     * returned:
87
     *
88
     * 1. Iterates through all examples folders for the given filename
89
     * 2. Checks the source folder for the given filename
90
     * 3. Checks the 'examples' folder in the current working directory for examples
91
     * 4. Checks the path relative to the current working directory for the given filename
92
     */
93 5
    private function getExampleFileContents(string $filename): ?array
94
    {
95 5
        $normalizedPath = null;
96
97 5
        foreach ($this->exampleDirectories as $directory) {
98 1
            $exampleFileFromConfig = $this->constructExamplePath($directory, $filename);
99 1
            if (is_readable($exampleFileFromConfig)) {
100 1
                $normalizedPath = $exampleFileFromConfig;
101 1
                break;
102
            }
103
        }
104
105 5
        if (! $normalizedPath) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $normalizedPath of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
106 4
            if (is_readable($this->getExamplePathFromSource($filename))) {
107 1
                $normalizedPath = $this->getExamplePathFromSource($filename);
108 3
            } elseif (is_readable($this->getExamplePathFromExampleDirectory($filename))) {
109 1
                $normalizedPath = $this->getExamplePathFromExampleDirectory($filename);
110 2
            } elseif (is_readable($filename)) {
111 1
                $normalizedPath = $filename;
112
            }
113
        }
114
115 5
        return ($normalizedPath && is_readable($normalizedPath)) ? file($normalizedPath) : null;
0 ignored issues
show
Bug Best Practice introduced by
The expression $normalizedPath of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
116
    }
117
118
    /**
119
     * Get example filepath based on the example directory inside your project.
120
     */
121 1
    private function getExamplePathFromExampleDirectory(string $file): string
122
    {
123 1
        return getcwd() . DIRECTORY_SEPARATOR . 'examples' . DIRECTORY_SEPARATOR . $file;
124
    }
125
126
    /**
127
     * Returns a path to the example file in the given directory..
128
     */
129 1
    private function constructExamplePath(string $directory, string $file): string
130
    {
131 1
        return rtrim($directory, '\\/') . DIRECTORY_SEPARATOR . $file;
132
    }
133
134
    /**
135
     * Get example filepath based on sourcecode.
136
     */
137 1
    private function getExamplePathFromSource(string $file): string
138
    {
139 1
        return sprintf(
140 1
            '%s%s%s',
141 1
            trim($this->getSourceDirectory(), '\\/'),
142 1
            DIRECTORY_SEPARATOR,
143 1
            trim($file, '"')
144
        );
145
    }
146
}
147