Skip to content

Commit

Permalink
[WIP] Initial work
Browse files Browse the repository at this point in the history
  • Loading branch information
Mateu Aguiló Bosch committed Jun 13, 2015
1 parent 91e8d5e commit 4adb865
Show file tree
Hide file tree
Showing 10 changed files with 251 additions and 6 deletions.
11 changes: 7 additions & 4 deletions bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

namespace Drupal\Composer\ClassLoader;

// Register the class loader.
$bootstrap = new AutoloaderBootstrap();
$bootstrap->register();

/**
* Class AutoloaderBootstrap
*
Expand All @@ -22,6 +26,9 @@ public function register() {
return;
}
}
// TODO: Load the *correct* composer.json in a decent OO way.
// Parse the composer.json.
Loader::setClassMap(json_decode(file_get_contents('composer.json')));
$this::load();
}

Expand All @@ -47,7 +54,3 @@ protected static function unload() {
}

}

// Register the class loader.
$bootstrap = new AutoloaderBootstrap();
$bootstrap->register();
10 changes: 10 additions & 0 deletions src/ClassLoaderException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

/**
* @file
* Contains Drupal\Composer\ClassLoader\ClassLoaderException.
*/

namespace Drupal\Composer\ClassLoader;

class ClassLoaderException extends \Exception {}
17 changes: 17 additions & 0 deletions src/Discovery/PathFinderBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,21 @@

class PathFinderBase implements PathFinderInterface {

/**
* The relative path.
*
* @var string
*/
protected $path;

/**
* Constructs a PathFinderBase object.
*
* @param string $path
* The relative path to find.
*/
public function __construct($path) {
$this->path = $path;
}

}
2 changes: 1 addition & 1 deletion src/Discovery/PathFinderContrib.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
namespace Drupal\Composer\ClassLoader\Discovery;


class PathFinderContrib implements PathFinderInterface {
class PathFinderContrib extends PathFinderBase implements PathFinderInterface {

}
2 changes: 1 addition & 1 deletion src/Discovery/PathFinderCore.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
namespace Drupal\Composer\ClassLoader\Discovery;


class PathFinderCore implements PathFinderInterface {
class PathFinderCore extends PathFinderBase implements PathFinderInterface {

}
20 changes: 20 additions & 0 deletions src/Discovery/PathFinderNull.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php
/**
* @file
* Contains Drupal\Composer\ClassLoader\Discovery\PathFinderNull.
*/

namespace Drupal\Composer\ClassLoader\Discovery;


class PathFinderNull extends PathFinderBase implements PathFinderInterface {

/**
* {@inheritdoc}
*/
public function requireFile() {
require_once $this->path;
return TRUE;
}

}
31 changes: 31 additions & 0 deletions src/Loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,35 @@

class Loader implements LoaderInterface {

/**
* Class maps.
*
* Contains the name of the class, including the namespace, as the key. The
* value is the file name with path tokens.
*
* @var
*/
protected static $classMap;

/**
* {@inheritdoc}
*/
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();
}

/**
* {@inheritdoc}
*/
public static function setClassMap(array $class_map) {
static::$classMap = $class_map;
}

}
18 changes: 18 additions & 0 deletions src/LoaderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,22 @@

interface LoaderInterface {

/**
* Autoload static method.
*
* @param string $class
* The name of the class to check or load.
*
* @return bool
* TRUE if the class is currently available, FALSE otherwise.
*/
public static function autoload($class);

/**
* Sets the class map.
*
* @param array $class_map
*/
public static function setClassMap(array $class_map);

}
126 changes: 126 additions & 0 deletions src/TokenResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?php

/**
* @file
* Contains Drupal\Composer\ClassLoader\TokenResolver.
*/

namespace Drupal\Composer\ClassLoader;


class TokenResolver implements TokenResolverInterface {

/**
* Path.
*
* @var string
*/
protected $path;

/**
* Supported tokens.
*
* The key is the name of the token, the value is the class that instantiates.
*
* @var array
*/
private $supportedTokens = array(
'DRUPAL_ROOT' => 'Discovery/PathFinderCore',
'DRUPAL_CONTRIB' => 'Discovery/PathFinderContrib',
);

/**
* Constructs a TokenResolver object.
*
* @param string $tokenized_path
* The path containing a potential token.
*/
public function __construct($tokenized_path = '') {
$this->path = $tokenized_path;
}

/**
* {@inheritdoc}
*/
public function resolve() {
// If the path is not tokenized, then return the NULL discovery object.
if (file_exists($this->path)) {
return new Discovery\PathFinderNull($this->path);
}
if (!$this->getToken()) {
return NULL;
}
$class_name = $this->getClassName();
$arguments[] = $this->cleanToken();
// Add more arguments to the constructor, like the module name.
$arguments += $this->parseArguments();
return new $class_name($arguments);
}

/**
* Removes the token from the tokenized path.
*
* @throws ClassLoaderException
* If no token can be found.
*
* @return string
* The cleaned path.
*/
protected function cleanToken() {
if ($token_name = $this->getToken()) {
// Remove the token and arguments and return the path.
$path = substr($this->path, strlen($token_name));
return preg_replace('/<.*>/', '', $path);
}
$message = sprintf('No token could be found in "%s". Available tokens are: %s.', $this->path, implode(', ', array_keys($this->supportedTokens)));
throw new ClassLoaderException($message);
}

/**
* Checks if the current tokenized path contains a known token.
*
* @return string
* The token found. NULL otherwise.
*/
protected function getToken() {
static $token_name;
if (isset($token_name)) {
return $token_name;
}
foreach (array_keys($this->supportedTokens) as $token_name) {
if (strpos($this->path, $token_name) === 0) {
return $token_name;
}
}
return NULL;
}

/**
* Gets the class name corresponding to the token.
*
* @return string
* The class name.
*/
protected function getClassName() {
$token_name = $this->getToken();
return $token_name ? $this->supportedTokens[$token_name] : NULL;
}

/**
* Gets the arguments in the token.
*
* @return string[]
* A numeric array containing the token arguments.
*/
protected function parseArguments() {
$token_name = $this->getToken();
$delimiter = '/';
$matches = array();
if (preg_match($delimiter . preg_quote($token_name) . '<(.+)>.*' . $delimiter, $this->path, $matches)) {
// Some arguments were found.
return explode(',', $matches[2]);
}
return array();
}

}
20 changes: 20 additions & 0 deletions src/TokenResolverInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

/**
* @file
* Contains Drupal\Composer\ClassLoader\TokenResolverInterface.
*/

namespace Drupal\Composer\ClassLoader;


interface TokenResolverInterface {

/**
* Finds the token in the give path and returns the discovery object.
*
* @return Discovery\PathFinderInterface
* The path finder class or NULL.
*/
public function resolve();
}

0 comments on commit 4adb865

Please sign in to comment.