-
Notifications
You must be signed in to change notification settings - Fork 821
/
ExtensionMiddleware.php
114 lines (102 loc) · 3.99 KB
/
ExtensionMiddleware.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<?php
namespace SilverStripe\Core\Config\Middleware;
use Generator;
use InvalidArgumentException;
use SilverStripe\Config\MergeStrategy\Priority;
use SilverStripe\Config\Middleware\Middleware;
use SilverStripe\Config\Middleware\MiddlewareCommon;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Extension;
use SilverStripe\ORM\DataExtension;
class ExtensionMiddleware implements Middleware
{
use MiddlewareCommon;
public function __construct($disableFlag = 0)
{
$this->setDisableFlag($disableFlag);
}
/**
* Get config for a class
*
* @param string $class Name of class
* @param int|true $excludeMiddleware Middleware disable flags
* @param callable $next Callback to next middleware
* @return array Complete class config
*/
public function getClassConfig($class, $excludeMiddleware, $next)
{
// Get base config
$config = $next($class, $excludeMiddleware);
if (!$this->enabled($excludeMiddleware)) {
return $config;
}
foreach ($this->getExtraConfig($class, $config, $excludeMiddleware) as $extra) {
$config = Priority::mergeArray($config, $extra);
}
return $config;
}
/**
* Applied config to a class from its extensions
*
* @param string $class
* @param array $classConfig
* @param int $excludeMiddleware
* @return Generator
*/
protected function getExtraConfig($class, $classConfig, $excludeMiddleware)
{
// Note: 'extensions' config needs to come from it's own middleware call in case
// applied by delta middleware (e.g. Object::add_extension)
$extensionSourceConfig = Config::inst()->get($class, null, Config::UNINHERITED | $excludeMiddleware | $this->disableFlag);
if (empty($extensionSourceConfig['extensions'])) {
return;
}
$extensions = $extensionSourceConfig['extensions'];
foreach ($extensions as $extension) {
// Allow removing extensions via yaml config by setting named extension config to null
if ($extension === null) {
continue;
}
list($extensionClass, $extensionArgs) = ClassInfo::parse_class_spec($extension);
// Strip service name specifier
$extensionClass = strtok($extensionClass ?? '', '.');
if (!class_exists($extensionClass ?? '')) {
throw new InvalidArgumentException("$class references nonexistent $extensionClass in 'extensions'");
}
// Init extension
call_user_func([$extensionClass, 'add_to_class'], $class, $extensionClass, $extensionArgs);
// Check class hierarchy from root up
foreach (ClassInfo::ancestry($extensionClass) as $extensionClassParent) {
// Skip base classes
switch ($extensionClassParent) {
case Extension::class:
case DataExtension::class:
continue 2;
default:
// continue
}
// Merge config from extension
$extensionConfig = Config::inst()->get(
$extensionClassParent,
null,
Config::EXCLUDE_EXTRA_SOURCES | Config::UNINHERITED
);
if ($extensionConfig) {
yield $extensionConfig;
}
if (ClassInfo::has_method_from($extensionClassParent, 'get_extra_config', $extensionClassParent)) {
$extensionConfig = call_user_func(
[ $extensionClassParent, 'get_extra_config' ],
$class,
$extensionClass,
$extensionArgs
);
if ($extensionConfig) {
yield $extensionConfig;
}
}
}
}
}
}