159 lines
4.6 KiB
PHP
159 lines
4.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* This file is part of phpDocumentor.
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*
|
|
* @link http://phpdoc.org
|
|
*/
|
|
|
|
namespace phpDocumentor\Reflection\DocBlock;
|
|
|
|
use phpDocumentor\Reflection\DocBlock\Tags\Example;
|
|
|
|
use function array_slice;
|
|
use function file;
|
|
use function getcwd;
|
|
use function implode;
|
|
use function is_readable;
|
|
use function rtrim;
|
|
use function sprintf;
|
|
use function trim;
|
|
|
|
use const DIRECTORY_SEPARATOR;
|
|
|
|
/**
|
|
* Class used to find an example file's location based on a given ExampleDescriptor.
|
|
*/
|
|
class ExampleFinder
|
|
{
|
|
private string $sourceDirectory = '';
|
|
|
|
/** @var string[] */
|
|
private array $exampleDirectories = [];
|
|
|
|
/**
|
|
* Attempts to find the example contents for the given descriptor.
|
|
*/
|
|
public function find(Example $example): string
|
|
{
|
|
$filename = $example->getFilePath();
|
|
|
|
$file = $this->getExampleFileContents($filename);
|
|
if (!$file) {
|
|
return sprintf('** File not found : %s **', $filename);
|
|
}
|
|
|
|
return implode('', array_slice($file, $example->getStartingLine() - 1, $example->getLineCount()));
|
|
}
|
|
|
|
/**
|
|
* Registers the project's root directory where an 'examples' folder can be expected.
|
|
*/
|
|
public function setSourceDirectory(string $directory = ''): void
|
|
{
|
|
$this->sourceDirectory = $directory;
|
|
}
|
|
|
|
/**
|
|
* Returns the project's root directory where an 'examples' folder can be expected.
|
|
*/
|
|
public function getSourceDirectory(): string
|
|
{
|
|
return $this->sourceDirectory;
|
|
}
|
|
|
|
/**
|
|
* Registers a series of directories that may contain examples.
|
|
*
|
|
* @param string[] $directories
|
|
*/
|
|
public function setExampleDirectories(array $directories): void
|
|
{
|
|
$this->exampleDirectories = $directories;
|
|
}
|
|
|
|
/**
|
|
* Returns a series of directories that may contain examples.
|
|
*
|
|
* @return string[]
|
|
*/
|
|
public function getExampleDirectories(): array
|
|
{
|
|
return $this->exampleDirectories;
|
|
}
|
|
|
|
/**
|
|
* Attempts to find the requested example file and returns its contents or null if no file was found.
|
|
*
|
|
* This method will try several methods in search of the given example file, the first one it encounters is
|
|
* returned:
|
|
*
|
|
* 1. Iterates through all examples folders for the given filename
|
|
* 2. Checks the source folder for the given filename
|
|
* 3. Checks the 'examples' folder in the current working directory for examples
|
|
* 4. Checks the path relative to the current working directory for the given filename
|
|
*
|
|
* @return string[] all lines of the example file
|
|
*/
|
|
private function getExampleFileContents(string $filename): ?array
|
|
{
|
|
$normalizedPath = null;
|
|
|
|
foreach ($this->exampleDirectories as $directory) {
|
|
$exampleFileFromConfig = $this->constructExamplePath($directory, $filename);
|
|
if (is_readable($exampleFileFromConfig)) {
|
|
$normalizedPath = $exampleFileFromConfig;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!$normalizedPath) {
|
|
if (is_readable($this->getExamplePathFromSource($filename))) {
|
|
$normalizedPath = $this->getExamplePathFromSource($filename);
|
|
} elseif (is_readable($this->getExamplePathFromExampleDirectory($filename))) {
|
|
$normalizedPath = $this->getExamplePathFromExampleDirectory($filename);
|
|
} elseif (is_readable($filename)) {
|
|
$normalizedPath = $filename;
|
|
}
|
|
}
|
|
|
|
$lines = $normalizedPath && is_readable($normalizedPath) ? file($normalizedPath) : false;
|
|
|
|
return $lines !== false ? $lines : null;
|
|
}
|
|
|
|
/**
|
|
* Get example filepath based on the example directory inside your project.
|
|
*/
|
|
private function getExamplePathFromExampleDirectory(string $file): string
|
|
{
|
|
return getcwd() . DIRECTORY_SEPARATOR . 'examples' . DIRECTORY_SEPARATOR . $file;
|
|
}
|
|
|
|
/**
|
|
* Returns a path to the example file in the given directory..
|
|
*/
|
|
private function constructExamplePath(string $directory, string $file): string
|
|
{
|
|
return rtrim($directory, '\\/') . DIRECTORY_SEPARATOR . $file;
|
|
}
|
|
|
|
/**
|
|
* Get example filepath based on sourcecode.
|
|
*/
|
|
private function getExamplePathFromSource(string $file): string
|
|
{
|
|
return sprintf(
|
|
'%s%s%s',
|
|
trim($this->getSourceDirectory(), '\\/'),
|
|
DIRECTORY_SEPARATOR,
|
|
trim($file, '"')
|
|
);
|
|
}
|
|
}
|