Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
70.27% covered (warning)
70.27%
26 / 37
50.00% covered (danger)
50.00%
2 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
PolicyManagerFactory
70.27% covered (warning)
70.27%
26 / 37
50.00% covered (danger)
50.00%
2 / 4
15.78
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createResourcePolicyProvider
92.31% covered (success)
92.31%
12 / 13
0.00% covered (danger)
0.00%
0 / 1
4.01
 createPolicyForBoundedContexts
54.55% covered (warning)
54.55%
12 / 22
0.00% covered (danger)
0.00%
0 / 1
9.38
 create
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2namespace Apie\Common\Wrappers;
3
4use Apie\Common\Config\Configuration;
5use Apie\Common\ValueObjects\EntityNamespace;
6use Apie\Core\BoundedContext\BoundedContextId;
7use Apie\Core\Lists\ItemHashmap;
8use Apie\Core\Policies\BoundedContextPolicyProvider;
9use Apie\Core\Policies\FallbackPolicy;
10use Apie\Core\Policies\PolicyManager;
11use Apie\Core\Policies\PolicyProviderHashmap;
12use Apie\Core\Policies\ResourcePolicyProvider;
13use Psr\Container\ContainerInterface as ContainerContainerInterface;
14use Symfony\Component\Finder\Finder;
15
16/**
17 * Creates a PolicyManager instance from the Apie configuration.
18 *
19 * @see Configuration in apie/apie-bundle for Symfony
20 * @see resources/apie.php in apie/laravel-apie for Laravel
21 */
22final class PolicyManagerFactory
23{
24    /**
25     * @param array<string, mixed> $boundedContexts
26     * @param array<string, string> $scanBoundedContexts
27     */
28    public function __construct(
29        private readonly array $boundedContexts,
30        private readonly array $scanBoundedContexts,
31        private readonly bool $defaultAllowIfNoPolicy,
32        private readonly ContainerContainerInterface $container
33    ) {
34    }
35
36    private function createResourcePolicyProvider(EntityNamespace $namespace, string $folder): ResourcePolicyProvider
37    {
38        $classes = $namespace->getClasses($folder);
39        $classPolicies = [];
40        foreach ($classes as $class) {
41            $shortName = $class->getShortName();
42            if (str_ends_with($shortName, 'Policy')) {
43                $shortName = substr($shortName, 0, -6);
44            }
45            $classPolicies[$shortName] = $this->container->has($class->name)
46                ? $this->container->get($class->name)
47                : $class->newInstance();
48        }
49        return new ResourcePolicyProvider(
50            new ItemHashmap($classPolicies),
51            new FallbackPolicy()
52        );
53    }
54
55    private function createPolicyForBoundedContexts(): BoundedContextPolicyProvider
56    {
57        $blocks = [];
58        foreach ($this->boundedContexts as $boundedContextId => $boundedContextConfig) {
59            $contextId = new BoundedContextId($boundedContextId);
60            $namespace = new EntityNamespace($boundedContextConfig['policy_namespace']);
61            $blocks[$contextId->toNative()] = $this->createResourcePolicyProvider($namespace, $boundedContextConfig['policy_folder']);
62        }
63        if (!empty($this->scanBoundedContexts['search_path'])
64            && !empty($this->scanBoundedContexts['search_namespace'])
65            && is_dir($this->scanBoundedContexts['search_path'])
66        ) {
67            $paths = Finder::create()
68                ->in($this->scanBoundedContexts['search_path'])
69                ->depth(0)
70                ->directories();
71            $namespace = new EntityNamespace($this->scanBoundedContexts['search_namespace']);
72            foreach ($paths as $path) {
73                $contextId = new BoundedContextId(strtolower($path->getBasename()));
74                $pathNamespace = $namespace->getChildNamespace($path->getBasename());
75                $namespace = $pathNamespace->getChildNamespace('Policies');
76                $blocks[$contextId->toNative()] = $this->createResourcePolicyProvider($namespace, $path . '/Policies');
77            }
78        }
79        return new BoundedContextPolicyProvider(
80            new PolicyProviderHashmap($blocks),
81            new FallbackPolicy()
82        );
83    }
84
85    public function create(): PolicyManager
86    {
87        return new PolicyManager($this->createPolicyForBoundedContexts(), $this->defaultAllowIfNoPolicy);
88    }
89}