Loader   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 204
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
dl 0
loc 204
rs 10
c 0
b 0
f 0
wmc 16
lcom 1
cbo 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A rescue() 0 6 1
A load() 0 22 3
A _error() 0 11 1
A _container() 0 22 3
B _fallback() 0 25 4
A _merge() 0 21 3
1
<?php
2
3
/**
4
 * Creates objects of a specified type using the configuration
5
 *
6
 * PHP Version 5
7
 *
8
 * @category  Core
9
 * @package   Service
10
 * @author    Hans-Joachim Piepereit <[email protected]>
11
 * @copyright 2013 cSphere Team
12
 * @license   http://opensource.org/licenses/bsd-license Simplified BSD License
13
 * @link      http://www.csphere.eu
14
 **/
15
16
namespace csphere\core\service;
17
18
/**
19
 * Creates objects of a specified type using the configuration
20
 *
21
 * @category  Core
22
 * @package   Service
23
 * @author    Hans-Joachim Piepereit <[email protected]>
24
 * @copyright 2013 cSphere Team
25
 * @license   http://opensource.org/licenses/bsd-license Simplified BSD License
26
 * @link      http://www.csphere.eu
27
 **/
28
29
class Loader
30
{
31
    /**
32
     * Array with config variables that is fetched later on
33
     **/
34
    private $_config = [];
35
36
    /**
37
     * Array with drivers that have already been configured
38
     **/
39
    private $_driver = [];
40
41
    /**
42
     * Determines if fallbacks are tried on problems
43
     **/
44
    private $_rescue = true;
45
46
    /**
47
     * Get configuration
48
     *
49
     * @param array $config Array with config flags to store
50
     *
51
     * @return \csphere\core\service\Loader
52
     **/
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
Coding Style introduced by
There must be no blank lines after the function comment
Loading history...
53
54
    public function __construct(array $config)
55
    {
56
        // Get content of config array and store it
57
        $this->_config = $config;
58
    }
59
60
    /**
61
     * Sets if a fallback should be tried on any driver problems
62
     *
63
     * @param boolean $fallback Fallback that defaults to true
64
     *
65
     * @return boolean
66
     **/
0 ignored issues
show
Coding Style introduced by
There must be no blank lines after the function comment
Loading history...
67
68
    public function rescue($fallback = true)
69
    {
70
        $this->_rescue = $fallback;
71
72
        return true;
73
    }
74
75
    /**
76
     * Service provider for core components
77
     *
78
     * @param string  $component Name of the core component with driver support
79
     * @param string  $driver    Driver name without any prefixes
80
     * @param array   $config    Configuration options for the driver
81
     * @param boolean $default   Set new driver as default for component
82
     *
83
     * @return object
84
     **/
0 ignored issues
show
Coding Style introduced by
There must be no blank lines after the function comment
Loading history...
85
86
    public function load(
87
        $component, $driver = '', array $config = [], $default = false
88
    ) {
89
        // Determine configuration details
90
        $config = $this->_merge($component, $driver, $config);
91
92
        // If it is unclear which object to use create it
93
        $key = $component . '_driver_' . $config['driver'];
94
95
        if (empty($this->_driver[$key])) {
96
97
            $this->_driver[$key] = $this->_container($component, $config);
98
        }
99
100
        // Store config of new default
101
        if ($default === true) {
102
103
            $this->_config[$component] = $config;
104
        }
105
106
        return $this->_driver[$key];
107
    }
108
109
    /**
110
     * Handles object creation errors by creating a log entry
111
     *
112
     * @param string     $component Name of the core component with driver support
113
     * @param string     $driver    Driver name without any prefixes
114
     * @param \Exception $exception Exception that occured and got catched
115
     *
116
     * @return string
117
     **/
0 ignored issues
show
Coding Style introduced by
There must be no blank lines after the function comment
Loading history...
118
119
    private function _error($component, $driver, \Exception $exception)
120
    {
121
        $msg = 'Message: Service Container failed to load component "'
122
             . $component . '" with driver "' . $driver . '"' . "\n"
123
             . 'Exception: ' . $exception->getMessage() . "\n"
124
             . 'Code: ' . $exception->getCode() . "\n"
125
             . 'File: ' . $exception->getFile() . "\n"
126
             . 'Line: ' . $exception->getLine();
127
128
        return $msg;
129
    }
130
131
    /**
132
     * Tries to create the requested component driver
133
     *
134
     * @param string $component Name of the core component with driver support
135
     * @param array  $config    Configuration options for the driver
136
     *
137
     * @return object
138
     **/
0 ignored issues
show
Coding Style introduced by
There must be no blank lines after the function comment
Loading history...
139
140
    private function _container($component, array $config)
141
    {
142
        // Check for empty driver
143
        if ($config['driver'] == '') {
144
145
            $config['driver'] = 'none';
146
        }
147
148
        // Create the destination object and return it
149
        $class = '\csphere\core\\' . $component . '\\driver_' . $config['driver'];
150
151
        try {
152
            $object = new $class($config);
153
154
        } catch (\Exception $driver_error) {
155
156
            // Try a fallback
157
            $object = $this->_fallback($component, $config, $driver_error);
158
        }
159
160
        return $object;
161
    }
162
163
    /**
164
     * Try to load something without fallbacks
165
     *
166
     * @param string     $component Name of the core component with driver support
167
     * @param array      $config    Configuration options for the driver
168
     * @param \Exception $exception Exception that occured
169
     *
170
     * @throws \Exception
171
     *
172
     * @return \csphere\core\service\Loader
173
     **/
0 ignored issues
show
Coding Style introduced by
There must be no blank lines after the function comment
Loading history...
174
175
    private function _fallback($component, array $config, $exception)
176
    {
177
        // Try to use a fallback to keep the process alive
178
        if ($config['driver'] != 'none' && $this->_rescue === true) {
179
180
            $old_driver       = $config['driver'];
181
            $config['driver'] = 'none';
182
183
            $object = $this->_container($component, $config);
184
185
            // Log the error
186
            $log = ($component == 'logs') ? $object : $this->load('logs');
187
188
            $msg = $this->_error($component, $old_driver, $exception);
189
190
            $log->log('errors', $msg);
191
192
            return $object;
193
194
        } else {
195
196
            // Rethrow exception otherwise
197
            throw $exception;
198
        }
199
    }
200
201
    /**
202
     * Handle config content of components
203
     *
204
     * @param string $component Name of the core component with driver support
205
     * @param string $driver    Driver name without any prefixes
206
     * @param array  $config    Configuration options for the driver
207
     *
208
     * @return array
209
     **/
0 ignored issues
show
Coding Style introduced by
There must be no blank lines after the function comment
Loading history...
210
211
    private function _merge($component, $driver, array $config)
212
    {
213
        // Check for configuration on empty name
214
        if (empty($driver)) {
215
216
            $driver = 'none';
217
218
            if (isset($this->_config[$component]['driver'])) {
219
220
                // Get driver from initial configuration
221
                $driver = $this->_config[$component]['driver'];
222
223
                $config = array_merge($this->_config[$component], $config);
224
            }
225
        }
226
227
        // Driver should be part of config array
228
        $config['driver'] = $driver;
229
230
        return $config;
231
    }
232
}
233