vendor/hwi/oauth-bundle/src/DependencyInjection/Configuration.php line 76
<?php/** This file is part of the HWIOAuthBundle package.** (c) Hardware Info <opensource@hardware.info>** For the full copyright and license information, please view the LICENSE* file that was distributed with this source code.*/namespace HWI\Bundle\OAuthBundle\DependencyInjection;use HWI\Bundle\OAuthBundle\OAuth\ResourceOwner\GenericOAuth1ResourceOwner;use HWI\Bundle\OAuthBundle\OAuth\ResourceOwner\GenericOAuth2ResourceOwner;use HWI\Bundle\OAuthBundle\OAuth\ResourceOwnerInterface;use Symfony\Component\Config\Definition\BaseNode;use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;use Symfony\Component\Config\Definition\Builder\TreeBuilder;use Symfony\Component\Config\Definition\ConfigurationInterface;use Symfony\Component\Finder\Finder;/*** Configuration for the extension.** @author Alexander <iam.asm89@gmail.com>*/final class Configuration implements ConfigurationInterface{/*** type => ResourceOwner mapping for hwi_oauth.resource_owner.*.class parameters.** @var array<string, class-string<GenericOAuth1ResourceOwner|GenericOAuth2ResourceOwner|ResourceOwnerInterface>>*/private static array $resourceOwnerTypesClassMap = [];/*** Array of supported resource owners.** @var array<string, string>*/private static array $resourceOwnerTypes = [];public function __construct(){if ([] === self::$resourceOwnerTypes) {self::loadResourceOwners();}}public static function getResourceOwnerTypesClassMap(): array{return self::$resourceOwnerTypesClassMap;}/*** Return the type (oauth1 or oauth2) of given resource owner.*/public static function getResourceOwnerType(string $resourceOwner): ?string{$resourceOwner = strtolower($resourceOwner);return self::$resourceOwnerTypes[$resourceOwner] ?? null;}/*** Checks that given resource owner is supported by this bundle.*/public static function isResourceOwnerSupported(string $resourceOwner): bool{return isset(self::$resourceOwnerTypes[strtolower($resourceOwner)]);}public static function registerResourceOwner(string $resourceOwnerClass): void{$reflection = new \ReflectionClass($resourceOwnerClass);if (!$reflection->implementsInterface(ResourceOwnerInterface::class)) {throw new \LogicException('Resource owner class should implement "ResourceOwnerInterface", or extended class "GenericOAuth1ResourceOwner"/"GenericOAuth2ResourceOwner".');}$type = \defined("$resourceOwnerClass::TYPE") ? $resourceOwnerClass::TYPE : null;if (null === $type) {if (preg_match('~(?P<resource_owner>[^\\\\]+)ResourceOwner$~', $resourceOwnerClass, $match)) {$type = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $match['resource_owner']));} else {throw new \LogicException(sprintf('Resource owner class either should have "TYPE" const defined or end with "ResourceOwner" so that type can be calculated by converting its class name without suffix to "snake_case". Given class name is "%s"', $resourceOwnerClass));}}$oAuth = 'unknown';if ($reflection->isSubclassOf(GenericOAuth2ResourceOwner::class)) {$oAuth = 'oauth2';} elseif ($reflection->isSubclassOf(GenericOAuth1ResourceOwner::class)) {$oAuth = 'oauth1';}self::$resourceOwnerTypes[$type] = $oAuth;self::$resourceOwnerTypesClassMap[$type] = $resourceOwnerClass;}/*** Generates the configuration tree builder.*/public function getConfigTreeBuilder(): TreeBuilder{$builder = new TreeBuilder('hwi_oauth');/** @var ArrayNodeDefinition $rootNode */$rootNode = $builder->getRootNode();$rootNode->fixXmlConfig('firewall_name')->children()->arrayNode('firewall_names')->setDeprecated(...$this->getDeprecationParams())->defaultValue([])->prototype('scalar')->end()->end()->scalarNode('target_path_parameter')->defaultNull()->end()->arrayNode('target_path_domains_whitelist')->defaultValue([])->prototype('scalar')->end()->end()->booleanNode('use_referer')->defaultFalse()->end()->booleanNode('failed_use_referer')->defaultFalse()->end()->scalarNode('failed_auth_path')->defaultValue('hwi_oauth_connect')->end()->scalarNode('grant_rule')->defaultValue('IS_AUTHENTICATED_REMEMBERED')->validate()->ifTrue(function ($role) {return !('IS_AUTHENTICATED_REMEMBERED' === $role || 'IS_AUTHENTICATED_FULLY' === $role);})->thenInvalid('Unknown grant role set "%s".')->end()->end()->end();$this->addConnectConfiguration($rootNode);$this->addResourceOwnersConfiguration($rootNode);return $builder;}private function addResourceOwnersConfiguration(ArrayNodeDefinition $node): void{$node->fixXmlConfig('resource_owner')->children()->arrayNode('resource_owners')->isRequired()->useAttributeAsKey('name')->prototype('array')->ignoreExtraKeys()->children()->scalarNode('base_url')->end()->scalarNode('access_token_url')->validate()->ifEmpty()->thenUnset()->end()->end()->scalarNode('authorization_url')->validate()->ifEmpty()->thenUnset()->end()->end()->scalarNode('request_token_url')->validate()->ifEmpty()->thenUnset()->end()->end()->scalarNode('revoke_token_url')->validate()->ifEmpty()->thenUnset()->end()->end()->scalarNode('infos_url')->validate()->ifEmpty()->thenUnset()->end()->end()->scalarNode('client_id')->cannotBeEmpty()->end()->scalarNode('client_secret')->cannotBeEmpty()->end()->scalarNode('realm')->validate()->ifEmpty()->thenUnset()->end()->end()->scalarNode('scope')->validate()->ifEmpty()->thenUnset()->end()->end()->scalarNode('user_response_class')->validate()->ifEmpty()->thenUnset()->end()->end()->scalarNode('service')->validate()->ifEmpty()->thenUnset()->end()->end()->scalarNode('class')->validate()->ifEmpty()->thenUnset()->end()->end()->scalarNode('type')// will be validated in ResourceOwnerCompilerPass, other apps can register own resource// owner maps later with tag hwi_oauth.resource_owner->validate()->ifEmpty()->thenUnset()->end()->end()->scalarNode('use_authorization_to_get_token')->validate()->ifEmpty()->thenUnset()->end()->end()->arrayNode('paths')->useAttributeAsKey('name')->prototype('variable')->validate()->ifTrue(function ($v) {if (null === $v) {return true;}if (\is_array($v)) {return 0 === \count($v);}if (\is_string($v)) {return empty($v);}return !is_numeric($v);})->thenInvalid('Path can be only string or array type.')->end()->end()->end()->arrayNode('options')->useAttributeAsKey('name')->prototype('scalar')->end()->end()->end()->validate()->ifTrue(function ($c) {// skip if this contains a serviceif (isset($c['service'])) {return false;}// for each type at least these have to be setforeach (['client_id', 'client_secret'] as $child) {if (!isset($c[$child])) {return true;}}if (!isset($c['type']) && !isset($c['class'])) {return true;}return false;})->thenInvalid("You should set at least the 'type' or 'class' with 'client_id' and the 'client_secret' of a resource owner.")->end()->validate()->ifTrue(function ($c) {return isset($c['type'], $c['class']);})->then(function ($c) {trigger_deprecation('hwi/oauth-bundle', '2.0', 'No need to set both "type" and "class" for resource owner.');return $c;})->end()->validate()->ifTrue(function ($c) {// Skip if this contains a service or a classif (isset($c['service']) || isset($c['class'])) {return false;}// Only validate the 'oauth2' and 'oauth1' typeif ('oauth2' !== $c['type'] && 'oauth1' !== $c['type']) {return false;}$children = ['authorization_url', 'access_token_url', 'request_token_url', 'infos_url'];foreach ($children as $child) {// This option exists only for OAuth1.0aif ('request_token_url' === $child && 'oauth2' === $c['type']) {continue;}if (!isset($c[$child])) {return true;}}return false;})->thenInvalid("All parameters are mandatory for types 'oauth2' and 'oauth1'. Check if you're missing one of: 'access_token_url', 'authorization_url', 'infos_url' and 'request_token_url' for 'oauth1'.")->end()->validate()->ifTrue(function ($c) {// skip if this contains a serviceif (isset($c['service']) || isset($c['class'])) {return false;}// Only validate the 'oauth2' and 'oauth1' typeif ('oauth2' !== $c['type'] && 'oauth1' !== $c['type']) {return false;}// one of this two options must be setif (0 === \count($c['paths'])) {return !isset($c['user_response_class']);}foreach (['identifier', 'nickname', 'realname'] as $child) {if (!isset($c['paths'][$child])) {return true;}}return false;})->thenInvalid("At least the 'identifier', 'nickname' and 'realname' paths should be configured for 'oauth2' and 'oauth1' types.")->end()->validate()->ifTrue(function ($c) {if (isset($c['service'])) {// ignore paths & options if none were setreturn 0 !== \count($c['paths']) || 0 !== \count($c['options']) || 3 < \count($c);}return false;})->thenInvalid("If you're setting a 'service', no other arguments should be set.")->end()->validate()->ifTrue(function ($c) {return isset($c['class']);})->then(function ($c) {self::registerResourceOwner($c['class']);return $c;})->end()->end()->end()->end();}private function addConnectConfiguration(ArrayNodeDefinition $node): void{$node->children()->arrayNode('connect')->children()->booleanNode('confirmation')->defaultTrue()->end()->scalarNode('account_connector')->cannotBeEmpty()->end()->scalarNode('registration_form_handler')->cannotBeEmpty()->end()->scalarNode('registration_form')->cannotBeEmpty()->end()->end()->end()->end();}private static function loadResourceOwners(): void{$files = (new Finder())->in(__DIR__.'/../OAuth/ResourceOwner')->name('~^(.+)ResourceOwner\.php$~')->files();foreach ($files as $f) {if (!str_contains($f->getFilename(), 'ResourceOwner')) {continue;}// Skip known abstract classesif (\in_array($f->getFilename(), ['AbstractResourceOwner.php', 'GenericOAuth1ResourceOwner.php', 'GenericOAuth2ResourceOwner.php'], true)) {continue;}self::registerResourceOwner('HWI\Bundle\OAuthBundle\OAuth\ResourceOwner\\'.str_replace('.php', '', $f->getFilename()));}}/*** Returns the correct deprecation params as an array for setDeprecated().** symfony/config v5.1 introduces a deprecation notice when calling* setDeprecated() with less than 3 args and the getDeprecation() method was* introduced at the same time. By checking if getDeprecation() exists,* we can determine the correct param count to use when calling setDeprecated().** @return string[]*/private function getDeprecationParams(): array{if (method_exists(BaseNode::class, 'getDeprecation')) {return ['hwi/oauth-bundle','2.0','option "%path%.%node%" is deprecated. Firewall names are collected automatically.',];}return ['Since hwi/oauth-bundle 2.0: option "hwi_oauth.firewall_names" is deprecated. Firewall names are collected automatically.'];}}