1
|
|
|
<?php
|
2
|
|
|
|
3
|
|
|
namespace PEIP\Factory;
|
4
|
|
|
/*
|
5
|
|
|
* To change this template, choose Tools | Templates
|
6
|
|
|
* and open the template in the editor.
|
7
|
|
|
*/
|
8
|
|
|
|
9
|
|
|
/**
|
10
|
|
|
* Description of ServiceFactory
|
11
|
|
|
*
|
12
|
|
|
* @author timo
|
13
|
|
|
*/
|
14
|
|
|
use PEIP\Util\Test;
|
15
|
|
|
use PEIP\Base\GenericBuilder;
|
16
|
|
|
use PEIP\Context\XMLContext;
|
17
|
|
|
|
18
|
|
|
class ServiceFactory {
|
19
|
|
|
/**
|
20
|
|
|
* Creates and initializes service instance from a given configuration.
|
21
|
|
|
*
|
22
|
|
|
* @access public
|
23
|
|
|
* @param $config configuration of the service
|
24
|
|
|
* @return object the initialized service instance
|
25
|
|
|
*/
|
26
|
|
|
public static function createService(array $config){
|
27
|
|
|
$args = array();
|
28
|
|
|
//build arguments for constructor
|
29
|
|
|
if(isset($config['constructor_arg'])){
|
30
|
|
|
foreach($config['constructor_arg'] as $arg){
|
31
|
|
|
$args[] = self::buildArg($arg);
|
32
|
|
|
}
|
33
|
|
|
}
|
34
|
|
|
return self::buildAndModify($config, $args);
|
35
|
|
|
}
|
36
|
|
|
|
37
|
|
|
/**
|
38
|
|
|
* Builds an arbitrary service/object instance from a config-obect.
|
39
|
|
|
*
|
40
|
|
|
* @static
|
41
|
|
|
* @access protected
|
42
|
|
|
* @param object $config configuration object to build a service instance from.
|
43
|
|
|
* @param array $arguments arguments for the service constructor
|
44
|
|
|
* @param string $defaultClass class to create instance for if none is set in config
|
45
|
|
|
* @return object build and modified srvice instance
|
46
|
|
|
*/
|
47
|
|
|
public static function doBuild($config, $arguments, $defaultClass = false){
|
48
|
|
|
$cls = isset($config["class"]) ? trim((string)$config["class"]) : (string)$defaultClass;
|
49
|
|
|
if($cls != ''){
|
50
|
|
|
try {
|
51
|
|
|
$constructor = isset($config["constructor"])?(string)$config["constructor"]:"";
|
52
|
|
|
if($constructor != '' && Test::assertMethod($cls, $constructor)){
|
53
|
|
|
$service = call_user_func_array(array($cls, $constructor), $arguments);
|
54
|
|
|
}else{
|
55
|
|
|
$service = self::build($cls, $arguments);
|
|
|
|
|
56
|
|
|
}
|
57
|
|
|
}catch(\Exception $e){
|
58
|
|
|
throw new \RuntimeException('Could not create Service "'.$cls.'" -> '.$e->getMessage());
|
59
|
|
|
}
|
60
|
|
|
}
|
61
|
|
|
if(is_object($service)){
|
62
|
|
|
return $service;
|
|
|
|
|
63
|
|
|
}
|
64
|
|
|
throw new \RuntimeException('Could not create Service "'.$cls.'". Class does not exist.');
|
65
|
|
|
}
|
66
|
|
|
|
67
|
|
|
|
68
|
|
|
/**
|
69
|
|
|
* Utility function to build an object instance for given class with given constructor-arguments.
|
70
|
|
|
*
|
71
|
|
|
* @see GenericBuilder
|
72
|
|
|
* @static
|
73
|
|
|
* @access protected
|
74
|
|
|
* @param object $className name of class to build instance for.
|
75
|
|
|
* @param array $arguments arguments for the constructor
|
76
|
|
|
* @return object build and modified srvice instance
|
77
|
|
|
*/
|
78
|
|
|
public static function build($className, $arguments){
|
79
|
|
|
return GenericBuilder::getInstance($className)->build($arguments);
|
|
|
|
|
80
|
|
|
}
|
81
|
|
|
|
82
|
|
|
/**
|
83
|
|
|
* Builds single argument (to call a method with later) from a config-obect.
|
84
|
|
|
*
|
85
|
|
|
* @access protected
|
86
|
|
|
* @param object $config configuration object to create argument from.
|
87
|
|
|
* @return mixed build argument
|
88
|
|
|
*/
|
89
|
|
View Code Duplication |
protected function buildArg($config){
|
|
|
|
|
90
|
|
|
if(trim((string)$config['value']) != ''){
|
91
|
|
|
$arg = (string)$config['value'];
|
92
|
|
|
}elseif($config->getName() == 'value'){
|
93
|
|
|
$arg = (string)$config;
|
94
|
|
|
}elseif($config->getName() == 'list'){
|
95
|
|
|
$arg = array();
|
96
|
|
|
foreach($config->children() as $entry){
|
97
|
|
|
if($entry->getName() == 'value'){
|
98
|
|
|
if($entry['key']){
|
99
|
|
|
$arg[(string)$entry['key']] = (string)$entry;
|
100
|
|
|
}else{
|
101
|
|
|
$arg[] = (string)$entry;
|
102
|
|
|
}
|
103
|
|
|
}elseif($entry->getName() == 'service'){
|
104
|
|
|
$arg[] = $this->provideService($entry);
|
|
|
|
|
105
|
|
|
}
|
106
|
|
|
}
|
107
|
|
|
}elseif($config->getName() == 'service'){
|
108
|
|
|
$arg = self::provideService($config);
|
|
|
|
|
109
|
|
|
}elseif($config->list){
|
110
|
|
|
$arg = $this->buildArg($config->list);
|
111
|
|
|
}elseif($config->service){
|
112
|
|
|
$arg = $this->buildArg($config->service);
|
113
|
|
|
}
|
114
|
|
|
return $arg;
|
|
|
|
|
115
|
|
|
}
|
116
|
|
|
|
117
|
|
|
/**
|
118
|
|
|
* Builds and modifies an arbitrary service/object instance from a config-obect.
|
119
|
|
|
*
|
120
|
|
|
* @see XMLContext::doBuild
|
121
|
|
|
* @see PEIP\Factory\ServiceFactory::modifyService
|
122
|
|
|
* @implements \PEIP\INF\Context\Context
|
123
|
|
|
* @access public
|
124
|
|
|
* @param object $config configuration array to build a service instance from.
|
125
|
|
|
* @param array $arguments arguments for the service constructor
|
126
|
|
|
* @param string $defaultClass class to create instance for if none is set in config
|
127
|
|
|
* @return object build and modified srvice instance
|
128
|
|
|
*/
|
129
|
|
|
public static function buildAndModify(array $config, $arguments, $defaultClass = ""){
|
130
|
|
|
if((isset($config["class"]) && "" != (string)$config["class"]) || $defaultClass !== ""){
|
131
|
|
|
$service = ServiceFactory::doBuild($config, $arguments, $defaultClass);
|
|
|
|
|
132
|
|
|
}else{
|
133
|
|
|
throw new \RuntimeException('Could not create Service. no class or reference given.');
|
134
|
|
|
}
|
135
|
|
|
if(isset($config["ref_property"])){
|
136
|
|
|
$service = $service->{(string)$config["ref_property"]};
|
137
|
|
|
}elseif(isset($config["ref_method"])){
|
138
|
|
|
$args = array();
|
139
|
|
|
if(isset($config['argument'])){
|
140
|
|
|
foreach($config['argument'] as $arg){
|
141
|
|
|
$args[] = $this->buildArg($arg);
|
|
|
|
|
142
|
|
|
}
|
143
|
|
|
}
|
144
|
|
|
$service = call_user_func_array(array($service, (string)$config["ref_method"]), $args);
|
145
|
|
|
}
|
146
|
|
|
if(!is_object($service)){
|
147
|
|
|
throw new \RuntimeException('Could not create Service.');
|
148
|
|
|
}
|
149
|
|
|
$service = self::modifyService($service, $config);
|
|
|
|
|
150
|
|
|
|
151
|
|
|
return $service;
|
152
|
|
|
}
|
153
|
|
|
|
154
|
|
|
|
155
|
|
|
/**
|
156
|
|
|
* Modifies a service instance from configuration.
|
157
|
|
|
* - Sets properties on the instance.
|
158
|
|
|
* -- Calls a public setter method if exists.
|
159
|
|
|
* -- Else sets a public property if exists.
|
160
|
|
|
* - Calls methods on the instance.
|
161
|
|
|
* - Registers listeners to events on the instance
|
162
|
|
|
*
|
163
|
|
|
* @access protected
|
164
|
|
|
* @param object $service the service instance to modify
|
165
|
|
|
* @param object $config configuration to get the modification instructions from.
|
166
|
|
|
* @return object the modificated service
|
167
|
|
|
*/
|
168
|
|
|
protected function modifyService($service, $config){
|
169
|
|
|
$config = is_array($config) ? new \ArrayObject($config) : $config;
|
170
|
|
|
// set instance properties
|
171
|
|
View Code Duplication |
if(isset($config->property)){
|
|
|
|
|
172
|
|
|
foreach($config->property as $property){
|
173
|
|
|
$arg = $this->buildArg($property);
|
174
|
|
|
if($arg){
|
175
|
|
|
$setter = self::getSetter($property);
|
|
|
|
|
176
|
|
|
if($setter && self::hasPublicProperty($service, 'Method', $setter)){
|
|
|
|
|
177
|
|
|
$service->{$setter}($arg);
|
178
|
|
|
}elseif(in_array($property, self::hasPublicProperty($service, 'Property', $setter))){
|
|
|
|
|
179
|
|
|
$service->$setter = $arg;
|
180
|
|
|
}
|
181
|
|
|
}
|
182
|
|
|
}
|
183
|
|
|
}
|
184
|
|
|
// call instance methods
|
185
|
|
View Code Duplication |
if(isset($config->action)){
|
|
|
|
|
186
|
|
|
foreach($config->action as $action){
|
187
|
|
|
$method = (string)$action['method'] != '' ? (string)$action['method'] : NULL;
|
188
|
|
|
if($method && self::hasPublicProperty($service, 'Method', $method)){
|
|
|
|
|
189
|
|
|
$args = array();
|
190
|
|
|
foreach($action->children() as $argument){
|
191
|
|
|
$args[] = $this->buildArg($argument);
|
192
|
|
|
}
|
193
|
|
|
call_user_func_array(array($service, (string)$action['method']), $args);
|
194
|
|
|
}
|
195
|
|
|
}
|
196
|
|
|
}
|
197
|
|
|
// register instance listeners
|
198
|
|
|
if($service instanceof \PEIP\INF\Event\Connectable){
|
199
|
|
View Code Duplication |
if(isset($config->listener)){
|
|
|
|
|
200
|
|
|
foreach($config->listener as $listenerConf){
|
201
|
|
|
$event = (string)$listenerConf['event'];
|
202
|
|
|
$listener = $this->provideService($listenerConf);
|
|
|
|
|
203
|
|
|
$service->connect($event, $listener);
|
204
|
|
|
}
|
205
|
|
|
}
|
206
|
|
|
}
|
207
|
|
|
return $service;
|
208
|
|
|
}
|
209
|
|
|
}
|
210
|
|
|
|
211
|
|
|
|
It seems like the type of the argument is not accepted by the function/method which you are calling.
In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.
We suggest to add an explicit type cast like in the following example: