/**
  * Creates a resource owner service.
  *
  * @example code
  * $extension = $container->getExtension('glory_oauth');
  * $extension->createOwnerService($container,$name,[]);
  * 
  * @param ContainerBuilder $container The container builder
  * @param string           $name      The name of the service
  * @param array            $options   Additional options of the service
  */
 public function createOwnerService(ContainerBuilder $container, $name, array $options)
 {
     $ownerId = 'glory_oauth.owner.' . $name;
     // alias services
     if (isset($options['service'])) {
         // set the appropriate name for aliased services, compiler pass depends on it
         $container->setAlias($ownerId, $options['service']);
     } else {
         $type = $options['type'];
         unset($options['type']);
         $definition = new DefinitionDecorator('glory_oauth.owner.abstract_' . GloryOAuthSupport::getOwnerType($type));
         $definition->setClass("%glory_oauth.owner.{$type}.class%");
         $container->setDefinition($ownerId, $definition);
         $definition->replaceArgument(2, $options)->replaceArgument(3, $name);
     }
     $container->getDefinition('glory_oauth.ownermap')->addMethodCall('addOwner', array($name, new Reference($ownerId)));
 }
 protected function addOwnersConfiguration(ArrayNodeDefinition $node)
 {
     $node->fixXmlConfig('owner')->children()->arrayNode('owners')->useAttributeAsKey('name')->prototype('array')->ignoreExtraKeys()->children()->scalarNode('base_url')->end()->scalarNode('access_token_url')->validate()->ifTrue(function ($v) {
         return empty($v);
     })->thenUnset()->end()->end()->scalarNode('authorization_url')->validate()->ifTrue(function ($v) {
         return empty($v);
     })->thenUnset()->end()->end()->scalarNode('request_token_url')->validate()->ifTrue(function ($v) {
         return empty($v);
     })->thenUnset()->end()->end()->scalarNode('revoke_token_url')->validate()->ifTrue(function ($v) {
         return empty($v);
     })->thenUnset()->end()->end()->scalarNode('infos_url')->validate()->ifTrue(function ($v) {
         return empty($v);
     })->thenUnset()->end()->end()->scalarNode('client_id')->cannotBeEmpty()->end()->scalarNode('client_secret')->cannotBeEmpty()->end()->scalarNode('realm')->validate()->ifTrue(function ($v) {
         return empty($v);
     })->thenUnset()->end()->end()->scalarNode('scope')->validate()->ifTrue(function ($v) {
         return empty($v);
     })->thenUnset()->end()->end()->scalarNode('user_response_class')->validate()->ifTrue(function ($v) {
         return empty($v);
     })->thenUnset()->end()->end()->scalarNode('service')->validate()->ifTrue(function ($v) {
         return empty($v);
     })->thenUnset()->end()->end()->scalarNode('type')->validate()->ifTrue(function ($type) {
         return !GloryOAuthSupport::isOwnerSupported($type);
     })->thenInvalid('Unknown resource owner type "%s".')->end()->validate()->ifTrue(function ($v) {
         return empty($v);
     })->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 service
         if (isset($c['service'])) {
             return false;
         }
         // for each type at least these have to be set
         foreach (array('type', 'client_id', 'client_secret') as $child) {
             if (!isset($c[$child])) {
                 return true;
             }
         }
         return false;
     })->thenInvalid("You should set at least the 'type', 'client_id' and the 'client_secret' of a resource owner.")->end()->validate()->ifTrue(function ($c) {
         // skip if this contains a service
         if (isset($c['service'])) {
             return false;
         }
         // Only validate the 'oauth2' and 'oauth1' type
         if ('oauth2' !== $c['type'] && 'oauth1' !== $c['type']) {
             return false;
         }
         $children = array('authorization_url', 'access_token_url', 'request_token_url', 'infos_url');
         foreach ($children as $child) {
             // This option exists only for OAuth1.0a
             if ('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 service
         if (isset($c['service'])) {
             return false;
         }
         // Only validate the 'oauth2' and 'oauth1' type
         if ('oauth2' !== $c['type'] && 'oauth1' !== $c['type']) {
             return false;
         }
         // one of this two options must be set
         if (0 === count($c['paths'])) {
             return !isset($c['user_response_class']);
         }
         foreach (array('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 set
             return 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()->end()->end()->end();
 }