1
|
|
|
<?php |
2
|
|
|
namespace samsonphp\config; |
3
|
|
|
|
4
|
|
|
use samsonphp\event\Event; |
5
|
|
|
|
6
|
|
|
/** |
7
|
|
|
* Generic SamsonPHP core configuration system |
8
|
|
|
* @author Vitaly Egorov <[email protected]> |
9
|
|
|
* @copyright 2014 SamsonOS |
10
|
|
|
*/ |
11
|
|
|
class Scheme |
12
|
|
|
{ |
13
|
|
|
/** Global/Default scheme marker */ |
14
|
|
|
const BASE = 'global'; |
15
|
|
|
|
16
|
|
|
/** Entity configuration file pattern */ |
17
|
|
|
const ENTITY_PATTERN = '*Config.php'; |
18
|
|
|
|
19
|
|
|
/** @var array Collection of file path -> class loaded */ |
20
|
|
|
protected static $classes = array(); |
21
|
|
|
|
22
|
|
|
/** @var string Current configuration environment */ |
23
|
|
|
protected $environment; |
24
|
|
|
|
25
|
|
|
/** @var array Configuration folder path array */ |
26
|
|
|
protected $path = array(); |
27
|
|
|
|
28
|
|
|
/** @var array Collection of module identifier => configurator class */ |
29
|
|
|
public $entities = array(); |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Create configuration instance. |
33
|
|
|
* |
34
|
|
|
* All module configurators must be stored within configuration base path, |
35
|
|
|
* by default this is stored in __SAMSON_CONFIG_PATH constant. |
36
|
|
|
* |
37
|
|
|
* Every environment configuration must be stored in sub-folder with the name of this |
38
|
|
|
* environment within base configuration folder. |
39
|
|
|
* |
40
|
|
|
* Configurators located at base root configuration folder considered as generic |
41
|
|
|
* module configurators. |
42
|
|
|
* |
43
|
|
|
* @param string $path Base path to configuration root folder |
44
|
|
|
* @param string $environment Configuration environment name |
45
|
|
|
*/ |
46
|
|
|
public function __construct($path, $environment) |
47
|
|
|
{ |
48
|
|
|
// Store current configuration environment |
49
|
|
|
$this->environment = $environment; |
50
|
|
|
|
51
|
|
|
// Check scheme folder existence |
52
|
|
|
if (file_exists($path)) { |
53
|
|
|
// Load scheme entities |
54
|
|
|
$this->load($path); |
55
|
|
|
} |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Load entity configuration classes for this scheme. |
60
|
|
|
* Function scans all required classes and matches them by |
61
|
|
|
* specified scheme path. |
62
|
|
|
*/ |
63
|
|
|
public function load($path = null) |
64
|
|
|
{ |
65
|
|
|
// Build path to environment configuration folder |
66
|
|
|
$this->path[] = $path; |
67
|
|
|
|
68
|
|
|
// Iterate all loaded classes matching class name pattern |
69
|
|
|
foreach (preg_grep(Entity::CLASS_PATTERN, get_declared_classes()) as $class) { |
70
|
|
|
// If this is a entity configuration class ancestor |
71
|
|
|
if (in_array(__NAMESPACE__.'\Entity', class_parents($class))) { |
72
|
|
|
// Get class reflection object |
73
|
|
|
$reflector = new \ReflectionClass($class); |
74
|
|
|
|
75
|
|
|
// If path to class file is in scheme paths collection |
76
|
|
|
if (in_array(dirname($reflector->getFileName()), $this->path)) { |
77
|
|
|
// Store module identifier - entity configuration object |
78
|
|
|
$this->entities[$this->identifier($class)] = new $class(); |
79
|
|
|
} |
80
|
|
|
} |
81
|
|
|
} |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* Convert entity configuration or object class name to identifier |
86
|
|
|
* @param string $class Entity configuration class name |
87
|
|
|
* @return string Entity real class name |
88
|
|
|
*/ |
89
|
|
|
public function identifier($class) |
90
|
|
|
{ |
91
|
|
|
// If namespace is present |
92
|
|
|
if (($classNamePos = strrpos($class, '\\')) !== false) { |
93
|
|
|
$class = substr($class, $classNamePos+1); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
// Remove only last occurrence of pattern |
97
|
|
|
return preg_replace(Entity::CLASS_PATTERN, '', strtolower($class)); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Retrieve entity configuration by identifier. |
102
|
|
|
* If entity configuration not found null will be |
103
|
|
|
* returned. |
104
|
|
|
* |
105
|
|
|
* @param string $identifier Entity identifier |
106
|
|
|
* @param mixed $entity Return found entity configuration pointer |
107
|
|
|
* @return Entity|boolean Entity configuration pointer or bool |
108
|
|
|
*/ |
109
|
|
|
public function & entity($identifier, & $entity = null) |
110
|
|
|
{ |
111
|
|
|
// Convert identifier of entity configuration name is passed |
112
|
|
|
$pointer = & $this->entities[$this->identifier($identifier)]; |
113
|
|
|
|
114
|
|
|
// PHP bugs =) We cannot assign referenced value pointer to array element |
115
|
|
|
$entity = $pointer; |
116
|
|
|
|
117
|
|
|
// Prepare return value - pointer or bool |
118
|
|
|
$return = (func_num_args() == 2) ? isset($pointer) : $pointer; |
119
|
|
|
|
120
|
|
|
// Also PHP bugs - we cannot return reference from ternary operator |
121
|
|
|
return $return; |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
/** |
125
|
|
|
* Perform object configuration with specific entity |
126
|
|
|
* @param mixed $object Object instance pointer |
127
|
|
|
* @param Entity $entity Entity configuration pointer |
128
|
|
|
* @param mixed $params Collection of parameters |
129
|
|
|
* @return bool True if everything went fine, otherwise false |
130
|
|
|
*/ |
131
|
|
|
protected function handleConfigure(& $object, Entity & $entity, $params = null) |
132
|
|
|
{ |
133
|
|
|
// If this class knows how to configure it self |
134
|
|
|
if (method_exists($object, 'configure')) { |
135
|
|
|
// Call custom configuration implementation |
136
|
|
|
return $object->configure($entity); |
137
|
|
|
} else { // Generic logic - implement entity configuration to object |
138
|
|
|
return $entity->configure($object, $params); |
139
|
|
|
} |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
/** |
143
|
|
|
* Configure object with configuration entity parameters. |
144
|
|
|
* |
145
|
|
|
* If now $identifier is passed - automatic identifier generation |
146
|
|
|
* will take place from object class name. |
147
|
|
|
* |
148
|
|
|
* If additional parameters key=>value collection is passed, they |
149
|
|
|
* will be used to configure object instead of entity configuration |
150
|
|
|
* class. |
151
|
|
|
* |
152
|
|
|
* @param mixed $object Object for configuration with entity |
153
|
|
|
* @param string $identifier Configuration entity name |
154
|
|
|
* @param array|null $params Collection of configuration parameters |
155
|
|
|
* |
156
|
|
|
* @return boolean True if we have successfully configured object |
157
|
|
|
*/ |
158
|
|
|
public function configure(& $object, $identifier = null, $params = null) |
159
|
|
|
{ |
160
|
|
|
/** @var Entity $pointer Pointer to entity instance */ |
161
|
|
|
$pointer = null; |
162
|
|
|
|
163
|
|
|
// If we have found this entity configuration, If no entity identifier is passed get it from object class |
164
|
|
|
if ($this->entity(isset($identifier) ? $identifier : get_class($object), $pointer)) { |
165
|
|
|
return $this->handleConfigure($object, $pointer, $params); |
166
|
|
|
} else { // Signal error |
167
|
|
|
Event::fire( |
168
|
|
|
'error', |
169
|
|
|
array( |
170
|
|
|
$this, |
171
|
|
|
'Cannot configure entity[' . $identifier . '] - Entity configuration does not exists' |
172
|
|
|
) |
173
|
|
|
); |
174
|
|
|
|
175
|
|
|
// We have failed |
176
|
|
|
return false; |
177
|
|
|
} |
178
|
|
|
} |
179
|
|
|
} |
180
|
|
|
|