mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
API Support trait loading
This commit is contained in:
parent
34b71cf6c8
commit
f26c220d86
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure namespace has no trailing slash, and namespaceBase does
|
||||||
|
$namespaceBase = '';
|
||||||
|
if ($namespace) {
|
||||||
|
$namespace = rtrim($namespace, '\\');
|
||||||
|
$namespaceBase = $namespace . '\\';
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($classes as $class) {
|
foreach ($classes as $class) {
|
||||||
$name = $class['className'];
|
$name = $namespaceBase . $class['className'];
|
||||||
if ($namespace) {
|
|
||||||
$namespace = rtrim($namespace, '\\');
|
|
||||||
$name = $namespace . '\\' . $name;
|
|
||||||
}
|
|
||||||
$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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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'),
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
trait TestTraitA {}
|
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace TestNamespace\Testing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
trait TestTraitB {
|
||||||
|
//put your code here
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user