Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | <?php |
||
| 28 | class ExpressiveAuraConfig implements ContainerConfigInterface |
||
| 29 | { |
||
| 30 | /** |
||
| 31 | * @var array |
||
| 32 | */ |
||
| 33 | private $config; |
||
| 34 | |||
| 35 | /** |
||
| 36 | * @param array $config |
||
| 37 | */ |
||
| 38 | public function __construct(array $config) |
||
| 39 | { |
||
| 40 | $this->config = $config; |
||
| 41 | } |
||
| 42 | |||
| 43 | /** |
||
| 44 | * Configure the container |
||
| 45 | * |
||
| 46 | * - Adds the 'config' service. |
||
| 47 | * - If delegators are defined, maps the service to lazyGetCall an |
||
| 48 | * ExpressiveAuraDelegatorFactory::build invocation using the configured |
||
| 49 | * delegator and whatever factory was responsible for it. |
||
| 50 | * - If factories are defined, maps each factory class as a lazily |
||
| 51 | * instantiable service, and the service to lazyGetCall the factory to |
||
| 52 | * create the instance. |
||
| 53 | * - If invokables are defined, maps each to lazyNew the target. |
||
| 54 | * - If aliases are defined, maps each to lazyGet the target. |
||
| 55 | * |
||
| 56 | * @param Container $container |
||
| 57 | * @return void |
||
| 58 | */ |
||
| 59 | public function define(Container $container) |
||
| 60 | { |
||
| 61 | // Convert config to an object and inject it |
||
| 62 | $container->set('config', new ArrayObject($this->config, ArrayObject::ARRAY_AS_PROPS)); |
||
| 63 | |||
| 64 | if (empty($this->config['dependencies'])) { |
||
| 65 | return; |
||
| 66 | } |
||
| 67 | |||
| 68 | $dependencies = $this->config['dependencies']; |
||
| 69 | |||
| 70 | // Inject delegator factories |
||
| 71 | // This is done early because Aura.Di does not allow modification of a |
||
| 72 | // service after creation. As such, we need to create custom factories |
||
| 73 | // for each service with delegators. |
||
| 74 | if (isset($dependencies['delegators'])) { |
||
| 75 | $dependencies = $this->marshalDelegators($container, $dependencies); |
||
| 76 | } |
||
| 77 | |||
| 78 | // Inject services |
||
| 79 | if (isset($dependencies['services'])) { |
||
| 80 | foreach ($dependencies['services'] as $name => $service) { |
||
| 81 | $container->set($name, $service); |
||
| 82 | } |
||
| 83 | } |
||
| 84 | |||
| 85 | // Inject factories |
||
| 86 | if (isset($dependencies['factories'])) { |
||
| 87 | foreach ($dependencies['factories'] as $service => $factory) { |
||
| 88 | $container->set($factory, $container->lazyNew($factory)); |
||
| 89 | $container->set($service, $container->lazyGetCall($factory, '__invoke', $container)); |
||
| 90 | } |
||
| 91 | } |
||
| 92 | |||
| 93 | // Inject invokables |
||
| 94 | if (isset($dependencies['invokables'])) { |
||
| 95 | foreach ($dependencies['invokables'] as $service => $class) { |
||
| 96 | $container->set($service, $container->lazyNew($class)); |
||
| 97 | } |
||
| 98 | } |
||
| 99 | |||
| 100 | // Inject aliases |
||
| 101 | if (isset($dependencies['aliases'])) { |
||
| 102 | foreach ($dependencies['aliases'] as $alias => $target) { |
||
| 103 | $container->set($alias, $container->lazyGet($target)); |
||
| 104 | } |
||
| 105 | } |
||
| 106 | } |
||
| 107 | |||
| 108 | /** |
||
| 109 | * This method is purposely a no-op. |
||
| 110 | * |
||
| 111 | * @param Container $container |
||
| 112 | * @return void |
||
| 113 | */ |
||
| 114 | public function modify(Container $container) |
||
| 115 | { |
||
| 116 | } |
||
| 117 | |||
| 118 | /** |
||
| 119 | * Marshal all services with delegators. |
||
| 120 | * |
||
| 121 | * @param Container $container |
||
| 122 | * @param array $dependencies |
||
| 123 | * @return array List of dependencies minus any services, factories, or |
||
| 124 | * invokables that match services using delegator factories. |
||
| 125 | */ |
||
| 126 | private function marshalDelegators(Container $container, array $dependencies) |
||
| 127 | { |
||
| 128 | foreach ($dependencies['delegators'] as $service => $delegatorNames) { |
||
| 129 | $factory = null; |
||
| 130 | |||
| 131 | if (isset($dependencies['services'][$service])) { |
||
| 132 | // Marshal from service |
||
| 133 | $instance = $dependencies['services'][$service]; |
||
| 134 | $factory = function () use ($instance) { |
||
| 135 | return $instance; |
||
| 136 | }; |
||
| 137 | unset($dependencies['service'][$service]); |
||
| 138 | } |
||
| 139 | |||
| 140 | if (isset($dependencies['factories'][$service])) { |
||
| 141 | // Marshal from factory |
||
| 142 | $serviceFactory = $dependencies['factories'][$service]; |
||
| 143 | $factory = function () use ($service, $serviceFactory, $container) { |
||
| 144 | return $serviceFactory($container, $service); |
||
| 145 | }; |
||
| 146 | unset($dependencies['factories'][$service]); |
||
| 147 | } |
||
| 148 | |||
| 149 | if (isset($dependencies['invokables'][$service])) { |
||
| 150 | // Marshal from invokable |
||
| 151 | $class = $dependencies['invokables'][$service]; |
||
| 152 | $factory = function () use ($class) { |
||
| 153 | return new $class(); |
||
| 154 | }; |
||
| 155 | unset($dependencies['invokables'][$service]); |
||
| 156 | } |
||
| 157 | |||
| 158 | if (! is_callable($factory)) { |
||
| 159 | continue; |
||
| 160 | } |
||
| 161 | |||
| 162 | $delegatorFactory = new ExpressiveAuraDelegatorFactory($delegatorNames, $factory); |
||
| 163 | $container->set( |
||
| 164 | $service, |
||
| 165 | $container->lazyGetCall($delegatorFactory, 'build', $container, $service) |
||
| 166 | ); |
||
| 167 | } |
||
| 168 | |||
| 169 | return $dependencies; |
||
| 170 | } |
||
| 171 | } |
||
| 172 |