Skip to content

Commit

Permalink
Initial class loader implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Mateu Aguiló Bosch committed Jun 14, 2015
1 parent 4adb865 commit 14bd674
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 9 deletions.
10 changes: 9 additions & 1 deletion src/Discovery/PathFinderBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
namespace Drupal\Composer\ClassLoader\Discovery;


class PathFinderBase implements PathFinderInterface {
abstract class PathFinderBase implements PathFinderInterface {

/**
* The relative path.
Expand All @@ -27,4 +27,12 @@ public function __construct($path) {
$this->path = $path;
}

/**
* {@inheritdoc}
*/
public function requireFile($seed) {
$real_path = $this->find($seed);
require_once $real_path;
}

}
60 changes: 60 additions & 0 deletions src/Discovery/PathFinderContrib.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,66 @@
namespace Drupal\Composer\ClassLoader\Discovery;


use Drupal\Composer\ClassLoader\ClassLoaderException;

class PathFinderContrib extends PathFinderBase implements PathFinderInterface {

/**
* The module name.
*
* @var string
*/
protected $moduleName;

/**
* Constructs a PathFinderContrib object.
*
* @param string $path
* The relative path to find.
* @param string $module_name
* The name of the contrib module to find.
*/
public function __construct($path, $module_name) {
$this->path = $path;
$this->moduleName = $module_name;
}

/**
* {@inheritdoc}
*/
public function find($seed) {
$core_finder = new PathFinderCore('');
if (!$core_path = $core_finder->find($seed)) {
return NULL;
}
$core_directory = new \RecursiveDirectoryIterator($core_path . '/sites', \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS);
$files_iterator = new \RecursiveIteratorIterator($core_directory, \RecursiveIteratorIterator::SELF_FIRST);
// Iterate over all of the directories under the sites directory.
foreach ($files_iterator as $path_name => $dir) {
/** @var $dir \SplFileInfo */
if (!$dir->isDir()) {
continue;
}
// Check if the current directory corresponds to the contrib we are
// looking for.
if ($this->isWantedContrib($dir)) {
return $dir->getPathname() . '/' . $this->path;
}
}
throw new ClassLoaderException(sprintf('Drupal module "%s" could not be found in the Drupal tree that contains: %s.', $this->moduleName, $seed));
}

/**
* Checks if the passed directory is the contrib module we are looking for.
*
* @param \SplFileInfo $dir
* The info object about the directory.
* @return bool
* TRUE if the contrib is detected. FALSE otherwise.
*/
protected function isWantedContrib(\SplFileInfo $dir) {
$info_file = $dir->getPathname() . '/' . $this->moduleName . '.info';
return file_exists($info_file);
}

}
66 changes: 66 additions & 0 deletions src/Discovery/PathFinderCore.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,73 @@

namespace Drupal\Composer\ClassLoader\Discovery;

use Drupal\Composer\ClassLoader\ClassLoaderException;

class PathFinderCore extends PathFinderBase implements PathFinderInterface {

/**
* {@inheritdoc}
*/
public function find($seed) {
$seed = realpath($seed);
// Try to create the iterator with the seed.
try {
$directory = new \DirectoryIterator($seed);
}
catch (\UnexpectedValueException $e) {
// If the seed was not a directory, then get the parent directory.
$path_info = pathinfo($seed);
$directory = new \DirectoryIterator($path_info['dirname']);
}
do {
if ($this->isDrupalRoot($directory)) {
return $directory . '/' . $this->path;
}
}
while ($directory = $this->getParentDirectory($directory));
throw new ClassLoaderException(sprintf('Drupal core directory could not be found as a parent of: %s.', $seed));
}

/**
* Checks if the passed directory is the Drupal root.
*
* @param \DirectoryIterator $directory
* The directory iterator item.
*
* @return bool
* TRUE if the passed directory is the Drupal root.
*/
protected function isDrupalRoot(\DirectoryIterator $directory) {
// Check if there is a COPYRIGHT.txt file in the directory.
foreach ($directory as $item) {
if (!$item->isFile() && $item->getFilename() != 'COPYRIGHT.txt') {
continue;
}
$line = fgets(fopen($item->getPathname(), 'r'));
return strpos($line, 'All Drupal code is Copyright') === 0;
}
return FALSE;
}

/**
* Gets the parent directory iterator.
*
* @param \DirectoryIterator $directory
* The current directory iterator.
*
* @return \DirectoryIterator
* The parent directory.
*/
protected function getParentDirectory(\DirectoryIterator $directory) {
$path_name = $directory->getPathname();
$path_info = pathinfo($path_name);
if (!empty($path_info['dirname'])) {
try {
return new \DirectoryIterator($path_info['dirname']);
}
catch (\UnexpectedValueException $e) {}
}
return NULL;
}

}
23 changes: 23 additions & 0 deletions src/Discovery/PathFinderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,27 @@

interface PathFinderInterface {

/**
* Finds and requires the current file.
*
* @throws \Drupal\Composer\ClassLoader\ClassLoaderException
* If the file could not be found.
*/
public function requireFile($seed);

/**
* Finds the current file in the file system.
*
* @param string $seed
* A path where to start looking for. Typically it will be the composer.json
* file name that contains the configuration.
*
* @throws \Drupal\Composer\ClassLoader\ClassLoaderException
* If the file could not be found.
*
* @return string
* The name of the real path. NULL if the file was not found.
*/
public function find($seed);

}
5 changes: 2 additions & 3 deletions src/Discovery/PathFinderNull.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ class PathFinderNull extends PathFinderBase implements PathFinderInterface {
/**
* {@inheritdoc}
*/
public function requireFile() {
require_once $this->path;
return TRUE;
public function find($seed) {
return $this->path;
}

}
16 changes: 11 additions & 5 deletions src/Loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,17 @@ public static function autoload($class) {
if (!in_array($class, static::$classMap)) {
return FALSE;
}
$resolver = new TokenResolver(static::$classMap[$class]);
$finder = $resolver->resolve();
// Have the path finder require the file and return TRUE or FALSE if it
// found the file or not.
return $finder->require();
try {
$resolver = new TokenResolver(static::$classMap[$class]);
$finder = $resolver->resolve();
// Have the path finder require the file and return TRUE or FALSE if it
// found the file or not.
$finder->requireFile();
return TRUE;
}
catch (ClassLoaderException $e) {
return FALSE;
}
}

/**
Expand Down

0 comments on commit 14bd674

Please sign in to comment.