Factory   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 137
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 2
dl 0
loc 137
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A createInstance() 0 19 3
A executeCallable() 0 15 3
A executeMethodBatch() 0 6 2
A executeMethod() 0 14 4
A afterCreation() 0 12 4
A executeCommonBatch() 0 11 3
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Di
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Di\Factory;
16
17
use Phossa2\Shared\Base\ObjectAbstract;
18
use Phossa2\Di\Exception\LogicException;
19
use Phossa2\Di\Interfaces\FactoryInterface;
20
use Phossa2\Di\Interfaces\ResolverInterface;
21
22
/**
23
 * Factory
24
 *
25
 * Wrapper of factorying methods for container
26
 *
27
 * @package Phossa2\Di
28
 * @author  Hong Zhang <[email protected]>
29
 * @see     FactoryInterface
30
 * @version 2.0.0
31
 * @since   2.0.0 added
32
 */
33
class Factory extends ObjectAbstract implements FactoryInterface
34
{
35
    use FactoryHelperTrait;
36
37
    /**
38
     * @param  ResolverInterface
39
     * @access public
40
     */
41
    public function __construct(ResolverInterface $resolver)
42
    {
43
        $this->setResolver($resolver);
44
    }
45
46
    /**
47
     * {@inheritDoc}
48
     */
49
    public function createInstance(/*# string */ $rawId, array $arguments)
50
    {
51
        // get service definition
52
        $def = $this->getDefinition($rawId, $arguments);
53
54
        // arguments
55
        $args = isset($def['args']) ? $def['args'] : [];
56
57
        if (is_string($def['class'])) {
58
            $obj = $this->constructObject($def['class'], $args);
59
        } else {
60
            $obj = $this->executeCallable($def['class'], $args);
61
        }
62
63
        // execute after-creation methods
64
        $this->afterCreation($obj, $def);
65
66
        return $obj;
67
    }
68
69
    /**
70
     * {@inheritDoc}
71
     */
72
    public function executeCallable($callable, array $arguments = [])
73
    {
74
        // not callable
75
        if (!is_callable($callable)) {
76
            return $callable;
77
        }
78
79
        if (!empty($arguments)) {
80
            $params = $this->getCallableParameters($callable);
81
            $args = $this->matchArguments($params, $arguments);
82
            return call_user_func_array($callable, $args);
83
        } else {
84
            return call_user_func($callable);
85
        }
86
    }
87
88
    /**
89
     * {@inheritDoc}
90
     */
91
    public function executeMethodBatch(array $methods, $object = null)
92
    {
93
        foreach ($this->mergeMethods($methods) as $method) {
94
            $this->executeMethod($method, $object);
95
        }
96
    }
97
98
    /**
99
     * if $object provided, build callable like [$object, $method] and execute it.
100
     *
101
     * method:
102
     *
103
     * - callable
104
     *
105
     * - array ['function', [ arguments...]]
106
     *
107
     * - array [callable, [ arguments ...]]
108
     *
109
     * - array ['method', [ arguments ...]]
110
     *   will be converted to [[$object, 'method'], [ ... ]]
111
     *
112
     * @param  array|callable method
113
     * @param  object|null $object to construct callable
114
     * @throws LogicException if something goes wrong
115
     * @access protected
116
     */
117
    protected function executeMethod($method, $object = null)
118
    {
119
        // is callable
120
        if (is_callable($method)) {
121
            return $this->executeCallable($method);
122
123
        // is [ method, arguments ]
124
        } elseif (isset($method[0])) {
125
            return $this->executeCallable(
126
                $this->getObjectMethod($object, $method[0]), // callable
127
                isset($method[1]) ? $method[1] : [] // arguments
128
            );
129
        }
130
    }
131
132
    /**
133
     * Things to do after an object created.
134
     *
135
     * @param  object $object
136
     * @param  array $definition service definition for $object
137
     * @access protected
138
     */
139
    protected function afterCreation($object, array $definition)
140
    {
141
        // execute methods of THIS object
142
        if (isset($definition['methods'])) {
143
            $this->executeMethodBatch($definition['methods'], $object);
144
        }
145
146
        // execute common methods for all objects
147
        if (!isset($definition['skip']) || !$definition['skip']) {
148
            $this->executeCommonBatch($object);
149
        }
150
    }
151
152
    /**
153
     * Execute common methods for all objects
154
     *
155
     * @param  object $object
156
     * @access protected
157
     */
158
    protected function executeCommonBatch($object)
159
    {
160
        $commons = $this->getCommonMethods();
161
        foreach ($commons as $pair) {
162
            $tester = $pair[0];
163
            $runner = $pair[1];
164
            if ($tester($object, $this)) {
165
                $this->executeMethod($runner, $object);
166
            }
167
        }
168
    }
169
}
170