API Support trait loading

This commit is contained in:
Damian Mooyman 2015-09-24 11:56:02 +12:00
parent 34b71cf6c8
commit f26c220d86
4 changed files with 73 additions and 15 deletions

View File

@ -30,6 +30,7 @@ class SS_ClassManifest {
protected $implementors = array(); protected $implementors = array();
protected $configs = array(); protected $configs = array();
protected $configDirs = array(); protected $configDirs = array();
protected $traits = array();
/** /**
* @return TokenisedRegularExpression * @return TokenisedRegularExpression
@ -81,6 +82,17 @@ class SS_ClassManifest {
)); ));
} }
/**
* @return TokenisedRegularExpression
*/
public static function get_trait_parser() {
return new \TokenisedRegularExpression(array(
0 => T_TRAIT,
1 => T_WHITESPACE,
2 => array(T_STRING, 'save_to' => 'traitName')
));
}
/** /**
* @return TokenisedRegularExpression * @return TokenisedRegularExpression
*/ */
@ -158,6 +170,7 @@ class SS_ClassManifest {
$this->implementors = $data['implementors']; $this->implementors = $data['implementors'];
$this->configs = $data['configs']; $this->configs = $data['configs'];
$this->configDirs = $data['configDirs']; $this->configDirs = $data['configDirs'];
$this->traits = $data['traits'];
} else { } else {
$this->regenerate($cache); $this->regenerate($cache);
} }
@ -177,6 +190,8 @@ class SS_ClassManifest {
return $this->classes[$name]; return $this->classes[$name];
} elseif (isset($this->interfaces[$name])) { } elseif (isset($this->interfaces[$name])) {
return $this->interfaces[$name]; return $this->interfaces[$name];
} elseif(isset($this->traits[$name])) {
return $this->traits[$name];
} }
} }
@ -198,6 +213,15 @@ class SS_ClassManifest {
return array_keys($this->classes); return array_keys($this->classes);
} }
/**
* Returns a lowercase array of all trait names in the manifest
*
* @return array
*/
public function getTraitNames() {
return array_keys($this->traits);
}
/** /**
* Returns an array of all the descendant data. * Returns an array of all the descendant data.
* *
@ -317,7 +341,7 @@ class SS_ClassManifest {
public function regenerate($cache = true) { public function regenerate($cache = true) {
$reset = array( $reset = array(
'classes', 'roots', 'children', 'descendants', 'interfaces', 'classes', 'roots', 'children', 'descendants', 'interfaces',
'implementors', 'configs', 'configDirs' 'implementors', 'configs', 'configDirs', 'traits'
); );
// Reset the manifest so stale info doesn't cause errors. // Reset the manifest so stale info doesn't cause errors.
@ -348,7 +372,8 @@ class SS_ClassManifest {
'interfaces' => $this->interfaces, 'interfaces' => $this->interfaces,
'implementors' => $this->implementors, 'implementors' => $this->implementors,
'configs' => $this->configs, 'configs' => $this->configs,
'configDirs' => $this->configDirs 'configDirs' => $this->configDirs,
'traits' => $this->traits,
); );
$this->cache->save($data, $this->cacheKey); $this->cache->save($data, $this->cacheKey);
} }
@ -488,6 +513,7 @@ class SS_ClassManifest {
$interfaces = null; $interfaces = null;
$namespace = null; $namespace = null;
$imports = null; $imports = null;
$traits = null;
// The results of individual file parses are cached, since only a few // The results of individual file parses are cached, since only a few
// files will have changed and TokenisedRegularExpression is quite // files will have changed and TokenisedRegularExpression is quite
@ -496,12 +522,14 @@ class SS_ClassManifest {
$file = file_get_contents($pathname); $file = file_get_contents($pathname);
$key = preg_replace('/[^a-zA-Z0-9_]/', '_', $basename) . '_' . md5($file); $key = preg_replace('/[^a-zA-Z0-9_]/', '_', $basename) . '_' . md5($file);
$valid = false;
if ($data = $this->cache->load($key)) { if ($data = $this->cache->load($key)) {
$valid = ( $valid = (
isset($data['classes']) && is_array($data['classes']) isset($data['classes']) && is_array($data['classes'])
&& isset($data['interfaces']) && is_array($data['interfaces']) && isset($data['interfaces']) && is_array($data['interfaces'])
&& isset($data['namespace']) && is_string($data['namespace']) && isset($data['namespace']) && is_string($data['namespace'])
&& isset($data['imports']) && is_array($data['imports']) && isset($data['imports']) && is_array($data['imports'])
&& isset($data['traits']) && is_array($data['traits'])
); );
if ($valid) { if ($valid) {
@ -509,13 +537,15 @@ class SS_ClassManifest {
$interfaces = $data['interfaces']; $interfaces = $data['interfaces'];
$namespace = $data['namespace']; $namespace = $data['namespace'];
$imports = $data['imports']; $imports = $data['imports'];
$traits = $data['traits'];
} }
} }
if (!$classes) { if (!$valid) {
$tokens = token_get_all($file); $tokens = token_get_all($file);
$classes = self::get_namespaced_class_parser()->findAll($tokens); $classes = self::get_namespaced_class_parser()->findAll($tokens);
$traits = self::get_trait_parser()->findAll($tokens);
$namespace = self::get_namespace_parser()->findAll($tokens); $namespace = self::get_namespace_parser()->findAll($tokens);
@ -533,17 +563,21 @@ class SS_ClassManifest {
'classes' => $classes, 'classes' => $classes,
'interfaces' => $interfaces, 'interfaces' => $interfaces,
'namespace' => $namespace, 'namespace' => $namespace,
'imports' => $imports 'imports' => $imports,
'traits' => $traits
); );
$this->cache->save($cache, $key); $this->cache->save($cache, $key);
} }
foreach ($classes as $class) { // Ensure namespace has no trailing slash, and namespaceBase does
$name = $class['className']; $namespaceBase = '';
if ($namespace) { if ($namespace) {
$namespace = rtrim($namespace, '\\'); $namespace = rtrim($namespace, '\\');
$name = $namespace . '\\' . $name; $namespaceBase = $namespace . '\\';
} }
foreach ($classes as $class) {
$name = $namespaceBase . $class['className'];
$extends = isset($class['extends']) ? implode('', $class['extends']) : null; $extends = isset($class['extends']) ? implode('', $class['extends']) : null;
$implements = isset($class['interfaces']) ? $class['interfaces'] : null; $implements = isset($class['interfaces']) ? $class['interfaces'] : null;
@ -599,12 +633,11 @@ class SS_ClassManifest {
} }
} }
$interfaceBase = '';
if ($namespace) {
$interfaceBase = $namespace . '\\';
}
foreach ($interfaces as $interface) { foreach ($interfaces as $interface) {
$this->interfaces[strtolower($interfaceBase . $interface['interfaceName'])] = $pathname; $this->interfaces[strtolower($namespaceBase . $interface['interfaceName'])] = $pathname;
}
foreach ($traits as $trait) {
$this->traits[strtolower($namespaceBase . $trait['traitName'])] = $pathname;
} }
} }

View File

@ -26,7 +26,9 @@ class ClassManifestTest extends SapphireTest {
'classa' => 'module/classes/ClassA.php', 'classa' => 'module/classes/ClassA.php',
'INTERFACEA' => 'module/interfaces/InterfaceA.php', 'INTERFACEA' => 'module/interfaces/InterfaceA.php',
'InterfaceA' => 'module/interfaces/InterfaceA.php', 'InterfaceA' => 'module/interfaces/InterfaceA.php',
'interfacea' => 'module/interfaces/InterfaceA.php' 'interfacea' => 'module/interfaces/InterfaceA.php',
'TestTraitA' => 'module/traits/TestTraitA.php',
'TestNamespace\Testing\TestTraitB' => 'module/traits/TestTraitB.php'
); );
foreach ($expect as $name => $path) { foreach ($expect as $name => $path) {
@ -53,6 +55,13 @@ class ClassManifestTest extends SapphireTest {
$this->manifest->getClassNames()); $this->manifest->getClassNames());
} }
public function testGetTraitNames() {
$this->assertEquals(
array('testtraita', 'testnamespace\testing\testtraitb'),
$this->manifest->getTraitNames()
);
}
public function testGetDescendants() { public function testGetDescendants() {
$expect = array( $expect = array(
'classa' => array('ClassC', 'ClassD'), 'classa' => array('ClassC', 'ClassD'),

View File

@ -0,0 +1,6 @@
<?php
/**
* @ignore
*/
trait TestTraitA {}

View File

@ -0,0 +1,10 @@
<?php
namespace TestNamespace\Testing;
/**
* @ignore
*/
trait TestTraitB {
//put your code here
}