Passed
Pull Request — master (#24)
by Arman
01:51
created

ServiceFactory::instantiate()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 9
c 0
b 0
f 0
dl 0
loc 19
rs 9.9666
cc 4
nc 4
nop 1
1
<?php
2
3
/**
4
 * Quantum PHP Framework
5
 *
6
 * An open source software development framework for PHP
7
 *
8
 * @package Quantum
9
 * @author Arman Ag. <[email protected]>
10
 * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
11
 * @link http://quantum.softberg.org/
12
 * @since 2.0.0
13
 */
14
15
namespace Quantum\Factory;
16
17
use Quantum\Exceptions\ExceptionMessages;
18
use Quantum\Exceptions\ServiceException;
19
use Quantum\Factory\ModelFactory;
20
use Quantum\Mvc\QtService;
21
22
/**
23
 * Class ServiceFactory
24
 * @package Quantum\Factory
25
 */
26
class ServiceFactory
27
{
28
29
    /**
30
     * Instantiated services 
31
     * @var array 
32
     */
33
    private $instantiated = [];
34
35
    /**
36
     * Creates and initialize the service once
37
     * @param string $serviceClass
38
     * @return QtService
39
     * @throws ServiceException
40
     */
41
    public function get($serviceClass): QtService
42
    {
43
        return $this->locate($serviceClass);
44
    }
45
46
    /**
47
     * Creates and initialize the service
48
     * @param string $serviceClass
49
     * @return QtService
50
     */
51
    public function create($serviceClass): QtService
52
    {
53
        return $this->instantiate($serviceClass);
54
    }
55
56
    /**
57
     * Locates the service
58
     * @param string $serviceClass
59
     * @return QtService
60
     */
61
    private function locate($serviceClass): QtService
62
    {
63
        if (isset($this->instantiated[$serviceClass])) {
64
            return $this->instantiated[$serviceClass];
65
        }
66
67
        return $this->instantiate($serviceClass);
68
    }
69
70
    /**
71
     * Instantiates the service
72
     * @param string $serviceClass
73
     * @return QtService
74
     * @throws ServiceException
75
     */
76
    private function instantiate($serviceClass): QtService
77
    {
78
        if (!class_exists($serviceClass)) {
79
            throw new ServiceException(_message(ExceptionMessages::SERVICE_NOT_FOUND, $serviceClass));
80
        }
81
        
82
        $service = $serviceClass::getInstance();
83
84
        if (!$service instanceof QtService) {
85
            throw new ServiceException(_message(ExceptionMessages::NOT_INSTANCE_OF_SERVICE, [$serviceClass, QtService::class]));
86
        }
87
88
        $this->instantiated[$serviceClass] = $service;
89
90
        if (method_exists($service, '__init')) {
91
            $service->__init(...$this->getArgs($service, '__init'));
92
        }
93
94
        return $service;
95
    }
96
97
    /**
98
     * Gets arguments
99
     * @param string $methodName
100
     * @param array $arguments
101
     * @return array
102
     */
103
    private function getArgs(QtService $service, $methodName, $arguments = [])
104
    {
105
        $args = [];
106
107
        $reflaction = new \ReflectionMethod($service, $methodName);
108
        $params = $reflaction->getParameters();
109
110
        foreach ($params as $param) {
111
            $paramType = $param->getType();
112
113
            if ($paramType && $paramType == ModelFactory::class) {
114
                array_push($args, new ModelFactory());
115
            } else {
116
                array_push($args, current($arguments));
117
                next($arguments);
118
            }
119
        }
120
121
        return $args;
122
    }
123
124
}
125