|
7 | 7 | use PHPStan\Drupal\ExtensionDiscovery;
|
8 | 8 | use PHPStan\Rules\Classes\EnhancedRequireParentConstructCallRule;
|
9 | 9 | use PHPStan\Rules\Classes\RequireParentConstructCallRule;
|
| 10 | +use Symfony\Component\Yaml\Yaml; |
10 | 11 |
|
11 | 12 | class DrupalExtension extends CompilerExtension
|
12 | 13 | {
|
@@ -103,12 +104,65 @@ public function loadConfiguration(): void
|
103 | 104 | }, $profiles);
|
104 | 105 | $extensionDiscovery->setProfileDirectories($profile_directories);
|
105 | 106 |
|
| 107 | + |
| 108 | + $serviceYamls = [ |
| 109 | + 'core' => $this->drupalRoot . '/core/core.services.yml', |
| 110 | + ]; |
| 111 | + $serviceClassProviders = [ |
| 112 | + 'core' => 'Drupal\Core\CoreServiceProvider', |
| 113 | + ]; |
| 114 | + |
106 | 115 | foreach ($extensionDiscovery->scan('module') as $extension) {
|
107 | 116 | $module_dir = $this->drupalRoot . '/' . $extension->getPath();
|
108 |
| - $servicesFileName = $module_dir . '/' . $extension->getName() . '.services.yml'; |
| 117 | + $moduleName = $extension->getName(); |
| 118 | + $servicesFileName = $module_dir . '/' . $moduleName . '.services.yml'; |
109 | 119 | if (file_exists($servicesFileName)) {
|
110 |
| - // @todo load and parse, push basic definitions into container parameters |
| 120 | + $serviceYamls[$moduleName] = $servicesFileName; |
| 121 | + } |
| 122 | + |
| 123 | + $camelized = $this->camelize($extension->getName()); |
| 124 | + $name = "{$camelized}ServiceProvider"; |
| 125 | + $class = "Drupal\\{$moduleName}\\{$name}"; |
| 126 | + |
| 127 | + if (class_exists($class)) { |
| 128 | + $serviceClassProviders[$moduleName] = $class; |
111 | 129 | }
|
112 | 130 | }
|
| 131 | + |
| 132 | + foreach ($serviceYamls as $extension => $serviceYaml) { |
| 133 | + $yaml = Yaml::parseFile($serviceYaml); |
| 134 | + // Weed out service files which only provide parameters. |
| 135 | + if (!isset($yaml['services']) || !is_array($yaml['services'])) { |
| 136 | + continue; |
| 137 | + } |
| 138 | + foreach ($yaml['services'] as $serviceId => $serviceDefinition) { |
| 139 | + // Prevent \Nette\DI\ContainerBuilder::completeStatement from array_walk_recursive into the arguments |
| 140 | + // and thinking these are real services for PHPStan's container. |
| 141 | + if (isset($serviceDefinition['arguments']) && is_array($serviceDefinition['arguments'])) { |
| 142 | + array_walk($serviceDefinition['arguments'], function (&$argument) { |
| 143 | + $argument = str_replace('@', '', $argument); |
| 144 | + }); |
| 145 | + } |
| 146 | + unset($serviceDefinition['tags']); |
| 147 | + // @todo sanitize "calls" and "configurator" and "factory" |
| 148 | + /** |
| 149 | + jsonapi.params.enhancer: |
| 150 | + class: Drupal\jsonapi\Routing\JsonApiParamEnhancer |
| 151 | + calls: |
| 152 | + - [setContainer, ['@service_container']] |
| 153 | + tags: |
| 154 | + - { name: route_enhancer } |
| 155 | + */ |
| 156 | + unset($serviceDefinition['calls']); |
| 157 | + unset($serviceDefinition['configurator']); |
| 158 | + unset($serviceDefinition['factory']); |
| 159 | + $builder->parameters['drupalServiceMap'][$serviceId] = $serviceDefinition; |
| 160 | + } |
| 161 | + } |
| 162 | + } |
| 163 | + |
| 164 | + protected function camelize($id) |
| 165 | + { |
| 166 | + return strtr(ucwords(strtr($id, ['_' => ' ', '.' => '_ ', '\\' => '_ '])), [' ' => '']); |
113 | 167 | }
|
114 | 168 | }
|
0 commit comments