Last active 1729618115

An example of creating a composite adapter for Apigility

matthew's Avatar matthew revised this gist 1729618115. Go to revision

No changes

matthew's Avatar Matthew Weier O'Phinney revised this gist 1429819734. Go to revision

3 files changed, 181 insertions

CompositeAdapter.php(file created)

@@ -0,0 +1,79 @@
1 + <?php
2 + use Zend\Http\Request;
3 + use Zend\Http\Response;;
4 + use ZF\MvcAuth\Authentication\AdapterInterface;
5 + use ZF\MvcAuth\Identity\IdentityInterface;
6 + use ZF\MvcAuth\MvcAuthEvent;
7 +
8 + class CompositeAdapter implements AdapterInterface
9 + {
10 + private $adapters = [];
11 +
12 + private $matched;
13 +
14 + public function attach(AdapterInterface $adapter)
15 + {
16 + if (in_array($adapter, $this->adapters, true)) {
17 + return;
18 + }
19 +
20 + $this->adapters[] = $adapter;
21 + }
22 +
23 + public function provides()
24 + {
25 + return array_reduce($this->adapters, function ($carry, $adapter) {
26 + $provides = array_merge($carry, $adapter->provides());
27 + return array_unique($provides);
28 + }, []);
29 + }
30 +
31 + public function matches($type)
32 + {
33 + $this->matched = null;
34 +
35 + foreach ($this->adapters as $adapter) {
36 + $match = $adapter->matches($type);
37 + if ($match) {
38 + $this->matched = $adapter;
39 + return true;
40 + }
41 + }
42 +
43 + return false;
44 + }
45 +
46 + public function getTypeFromRequest(Request $request)
47 + {
48 + foreach ($this->adapters as $adapter) {
49 + $type = $adapter->getTypeFromRequest($request);
50 + if (false !== $type) {
51 + return $type;
52 + }
53 + }
54 + return false;
55 + }
56 +
57 + public function preAuth(Request $request, Response $response)
58 + {
59 + foreach ($this->adapters as $adapter) {
60 + $result = $adapter->preAuth($request, $response);
61 + if ($result instanceof Response) {
62 + return $result;
63 + }
64 + }
65 + }
66 +
67 + public function authenticate(Request $request, Response $response, MvcAuthEvent $mvcAuthEvent)
68 + {
69 + if (! $this->matched) {
70 + return false;
71 + }
72 +
73 + // Reset $matched so that subsequent calls fail
74 + $adapter = $this->matched;
75 + $this->matched = null;
76 +
77 + return $adapter->authenticate($request, $response, $mvcAuthEvent);
78 + }
79 + }

CompositeAdapterDelegatorFactory.php(file created)

@@ -0,0 +1,38 @@
1 + <?php
2 +
3 + use Zend\ServiceManager\DelegatorFactoryInterface;
4 + use Zend\ServiceManager\ServiceLocatorInterface;
5 +
6 + /**
7 + * Delegator factory for adding the CompositeAdapter.
8 + *
9 + * This delegator factory assumes that you've registered the CompositeAdapter
10 + * as the service 'CompositeAdapter'.
11 + *
12 + * Attach it to the DefaultAuthenticationListener using:
13 + *
14 + * ```php
15 + * 'service_manager' => array(
16 + * 'delegators' => array(
17 + * 'ZF\MvcAuth\Authentication\DefaultAuthenticationListener' => array(
18 + * 'CompositeAdapterDelegatorFactory',
19 + * ),
20 + * ),
21 + * ),
22 + * ```
23 + */
24 + class CompositeAdapterDelegatorFactory implements DelegatorFactoryInterface
25 + {
26 + public function createDelegatorWithName(
27 + ServiceLocatorInterface $services,
28 + $name,
29 + $requestedName,
30 + $callback
31 + ) {
32 + $listener = $callback();
33 +
34 + $composite = $services->get('CompositeAdapter');
35 + $listener->attach($composite);
36 + return $listener;
37 + }
38 + }

CompositeAdapterFactory.php(file created)

@@ -0,0 +1,64 @@
1 + <?php
2 + use ZF\MvcAuth\Factory\AuthenticationHttpAdapterFactory;
3 + use ZF\MvcAuth\Factory\AuthenticationOAuth2AdapterFactory;
4 +
5 + class CompositeAdapterFactory
6 + {
7 + public function __invoke($services)
8 + {
9 + $config = $services->get('Config');
10 + $adapters = [];
11 +
12 + /*
13 + * You could put the key somewhere else. The idea, though, is that each
14 + * named adapter matches a key under zf-mvc-auth.authentication.adapters. The
15 + * primary problem with this approach is that you'll get two instances
16 + * for adapters you attach to the composite adapter. One alternative is
17 + * to use the approach in ZF\MvcAuth\Factory\AuthenticationAdapterDelegatorFactory
18 + * and define the configuration for the attached adapters within this
19 + * array, and instantiate them here only. Of course, that means you can
20 + * only configure those adapters manually.
21 + */
22 + if (isset($config['zf-mvc-auth']['authentication']['composite'])
23 + && is_array($config['zf-mvc-auth']['authentication']['composite'])
24 + ) {
25 + $adapters = $config['zf-mvc-auth']['authentication']['composite'];
26 + }
27 +
28 + $composite = new CompositeAdapter();
29 +
30 + foreach ($adapters as $adapterName) {
31 + $adapter = $this->getAdapter(
32 + $adapterName,
33 + $config['zf-mvc-auth']['authentication']['adapters'],
34 + $services
35 + );
36 + if (! $adapter) {
37 + continue;
38 + }
39 + $composite->attach($adapter);
40 + }
41 +
42 + return $composite;
43 + }
44 +
45 + private function getAdapter($adapterName, array $config, $services)
46 + {
47 + if (! isset $config[$adapterName]
48 + || ! isset($config[$adapterName]['adapter'])
49 + || ! is_string($config[$adapterName]['adapter'])
50 + ) {
51 + return false;
52 + }
53 +
54 + $config = $config[$adapterName];
55 + switch ($config['adapter']) {
56 + case 'ZF\MvcAuth\Authentication\HttpAdapter':
57 + return AuthenticationHttpAdapterFactory::factory($adapterName, $config, $services);
58 + case 'ZF\MvcAuth\Authentication\OAuth2Adapter':
59 + return AuthenticationOAuth2AdapterFactory::factory($adapterName, $config, $services);
60 + default:
61 + return false;
62 + }
63 + }
64 + }
Newer Older