Manager::change()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 9.0856
c 0
b 0
f 0
cc 2
eloc 10
nc 2
nop 1
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: egorov
5
 * Date: 06.01.2015
6
 * Time: 16:59
7
 */
8
namespace samsonphp\config;
9
10
use samsonphp\event\Event;
11
12
/**
13
 * Configuration scheme manager
14
 * @package samsonphp\config
15
 */
16
class Manager
17
{
18
    /** @var array Collection of file path -> class loaded */
19
    protected static $classes = array();
20
21
    /** @var array Collection of files in current init */
22
    protected static $files = array();
23
24
    /**
25
     * Load all entity configuration classes in specific location.
26
     *
27
     * All module files must match Entity::FILE_PATTERN to be
28
     * loaded.
29
     *
30
     * @param string $path Path for importing classes
31
     */
32
    public static function import($path)
33
    {
34
        // Read all files in path
35
        self::$files = glob($path .'/'. Entity::FILE_PATTERN);
36
37
        // Fill array of entity files with keys of file names without extension
38
        foreach (self::$files as $file) {
39
            $file = realpath($file);
40
            // If we have not already loaded this class before with other schemes
41
            if (!isset(self::$classes[$file])) {
42
                // Store loaded classes
43
                $classes = get_declared_classes();
44
45
                // Load entity configuration file
46
                require_once($file);
47
48
                // Get loaded class - store class to static collection
49
                $classes = array_diff(get_declared_classes(), $classes);
50
                self::$classes[$file] = end($classes);
51
            }
52
        }
53
    }
54
55
    /** @var Scheme[] Collection of available schemes */
56
    public $schemes = array();
57
58
    /** @var  Scheme Pointer to current active configuration scheme */
59
    protected $active;
60
61
    /**
62
     * Initialize all configuration logic
63
     */
64
    public function __construct()
65
    {
66
        // Add class auto loader
67
        spl_autoload_register(array($this, 'autoload'));
68
69
        // Subscribe active configuration scheme to core module configure event
70
        Event::subscribe('core.environment.change', array($this, 'change'));
71
    }
72
73
    /**
74
     * Configuration class autoloader.
75
     * It helps resolve single configuration entity configuration dependencies
76
     * @param string $className Class name for loading
77
     */
78
    public function autoload($className)
79
    {
80
        // If namespace is present
81
        $class = substr($className, strrpos($className, '\\')+1);
82
83
        // Try to find class file by class name without namespace
84
        $matches = preg_grep('/'.$class.'/i', self::$files);
85
        if (sizeof($matches)) {
86
            require_once(end($matches));
87
        }
88
    }
89
90
    /**
91
     * Switch active environment
92
     * @param string $environment Configuration environment identifier
93
     */
94
    public function change($environment = Scheme::BASE)
95
    {
96
        // Switch to configuration environment
97
        $this->active = & $this->schemes[$environment];
98
99
        // Subscribe active configuration scheme to core module configure event
100
        Event::subscribe('core.module.configure', array($this, 'configure'));
101
102
        // If we have successfully changed configuration scheme
103
        if (!isset($this->active)) {
104
            // Signal error
105
            Event::fire(
106
                'error',
107
                array(
108
                    $this,
109
                    'Cannot change configuration scheme to ['.$environment.'] - Configuration scheme does not exists'
110
                )
111
            );
112
113
            // Set global scheme as active
114
            $this->active = & $this->schemes[Scheme::BASE];
115
        }
116
    }
117
118
    /**
119
     * Initialize all configuration logic
120
     * @param string $basePath Path to configuration base folder
121
     */
122
    public function init($basePath)
123
    {
124
        // Create global scheme instance
125
        $this->create($basePath, Scheme::BASE);
126
127
        // Switch to global environment
128
        $this->change();
129
130
        // Read all directories in base configuration path
131
        foreach (glob($basePath . '*', GLOB_ONLYDIR) as $path) {
132
            // Create new configuration scheme
133
            $this->create($path);
134
        }
135
    }
136
137
    /**
138
     * Create configuration scheme
139
     * @param string $path Path to configuration scheme folder
140
     * @param string $environment Configuration scheme environment identifier
141
     */
142
    public function create($path, $environment = null)
143
    {
144
        // Import all valid entity configuration classes from path
145
        self::import($path);
146
147
        // If no environment identifier is passed - use it from path
148
        $environment = !isset($environment) ? basename($path) : $environment;
149
150
        // Pointer to a configuration scheme
151
        $pointer = & $this->schemes[$environment];
152
153
        // Check if have NOT already created configuration for this environment
154
        if (!isset($pointer)) {
155
            $pointer = new Scheme(realpath($path . '/'), $environment);
156
        } else { // Load data to existing configuration scheme
157
            $pointer->load(realpath($path . '/'));
158
        }
159
    }
160
161
    /**
162
     * Configure object with current configuration scheme entity parameters.
163
     *
164
     * If now $identifier is passed - automatic identifier generation
165
     * will take place from object class name.
166
     *
167
     * If additional parameters key=>value collection is passed, they
168
     * will be used to configure object instead of entity configuration
169
     * class.
170
     *
171
     * If current configuration scheme has no entity configuration for
172
     * passed object - global configuration scheme will be used.
173
     *
174
     * @param mixed $object Object for configuration with entity
175
     * @param string $identifier Configuration entity name
176
     * @param array|null $params Collection of configuration parameters
177
     */
178
    public function configure(& $object, $identifier = null, $params = null)
179
    {
180
        // Try to configure using current scheme
181
        if (!$this->active->configure($object, $identifier, $params)) {
182
            // Get pointer to global scheme
183
            $base = & $this->schemes[Scheme::BASE];
184
            if (isset($base) && $base !== $this->active) {
185
                // Call global scheme for configuration
186
                $base->configure($object, $identifier, $params);
187
            }
188
        }
189
    }
190
}
191