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