/www/slight

To get this branch, use:
bzr branch http://bzr.ed.am/www/slight

« back to all changes in this revision

Viewing changes to flight/core/Loader.php

  • Committer: Tim Marston
  • Date: 2015-08-05 18:48:29 UTC
  • Revision ID: tim@ed.am-20150805184829-c3qj13d1h89pkb2l
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * Flight: An extensible micro-framework.
 
4
 *
 
5
 * @copyright   Copyright (c) 2011, Mike Cao <mike@mikecao.com>
 
6
 * @license     MIT, http://flightphp.com/license
 
7
 */
 
8
 
 
9
namespace flight\core;
 
10
 
 
11
/**
 
12
 * The Loader class is responsible for loading objects. It maintains
 
13
 * a list of reusable class instances and can generate a new class
 
14
 * instances with custom initialization parameters. It also performs
 
15
 * class autoloading.
 
16
 */
 
17
class Loader {
 
18
    /**
 
19
     * Registered classes.
 
20
     *
 
21
     * @var array
 
22
     */
 
23
    protected $classes = array();
 
24
 
 
25
    /**
 
26
     * Class instances.
 
27
     *
 
28
     * @var array
 
29
     */
 
30
    protected $instances = array();
 
31
 
 
32
    /**
 
33
     * Autoload directories.
 
34
     *
 
35
     * @var array
 
36
     */
 
37
    protected static $dirs = array();
 
38
 
 
39
    /**
 
40
     * Registers a class.
 
41
     *
 
42
     * @param string $name Registry name
 
43
     * @param string|callable $class Class name or function to instantiate class
 
44
     * @param array $params Class initialization parameters
 
45
     * @param callback $callback Function to call after object instantiation
 
46
     */
 
47
    public function register($name, $class, array $params = array(), $callback = null) {
 
48
        unset($this->instances[$name]);
 
49
 
 
50
        $this->classes[$name] = array($class, $params, $callback);
 
51
    }
 
52
 
 
53
    /**
 
54
     * Unregisters a class.
 
55
     *
 
56
     * @param string $name Registry name
 
57
     */
 
58
    public function unregister($name) {
 
59
        unset($this->classes[$name]);
 
60
    }
 
61
 
 
62
    /**
 
63
     * Loads a registered class.
 
64
     *
 
65
     * @param string $name Method name
 
66
     * @param bool $shared Shared instance
 
67
     * @return object Class instance
 
68
     */
 
69
    public function load($name, $shared = true) {
 
70
        $obj = null;
 
71
 
 
72
        if (isset($this->classes[$name])) {
 
73
            list($class, $params, $callback) = $this->classes[$name];
 
74
 
 
75
            $exists = isset($this->instances[$name]);
 
76
 
 
77
            if ($shared) {
 
78
                $obj = ($exists) ?
 
79
                    $this->getInstance($name) :
 
80
                    $this->newInstance($class, $params);
 
81
                
 
82
                if (!$exists) {
 
83
                    $this->instances[$name] = $obj;
 
84
                }
 
85
            }
 
86
            else {
 
87
                $obj = $this->newInstance($class, $params);
 
88
            }
 
89
 
 
90
            if ($callback && (!$shared || !$exists)) {
 
91
                $ref = array(&$obj);
 
92
                call_user_func_array($callback, $ref);
 
93
            }
 
94
        }
 
95
 
 
96
        return $obj;
 
97
    }
 
98
 
 
99
    /**
 
100
     * Gets a single instance of a class.
 
101
     *
 
102
     * @param string $name Instance name
 
103
     * @return object Class instance
 
104
     */
 
105
    public function getInstance($name) {
 
106
        return isset($this->instances[$name]) ? $this->instances[$name] : null;
 
107
    }
 
108
 
 
109
    /**
 
110
     * Gets a new instance of a class.
 
111
     *
 
112
     * @param string|callable $class Class name or callback function to instantiate class
 
113
     * @param array $params Class initialization parameters
 
114
     * @return object Class instance
 
115
     */
 
116
    public function newInstance($class, array $params = array()) {
 
117
        if (is_callable($class)) {
 
118
            return call_user_func_array($class, $params);
 
119
        }
 
120
 
 
121
        switch (count($params)) {
 
122
            case 0:
 
123
                return new $class();
 
124
            case 1:
 
125
                return new $class($params[0]);
 
126
            case 2:
 
127
                return new $class($params[0], $params[1]);
 
128
            case 3:
 
129
                return new $class($params[0], $params[1], $params[2]);
 
130
            case 4:
 
131
                return new $class($params[0], $params[1], $params[2], $params[3]);
 
132
            case 5:
 
133
                return new $class($params[0], $params[1], $params[2], $params[3], $params[4]);
 
134
            default:
 
135
                $refClass = new \ReflectionClass($class);
 
136
                return $refClass->newInstanceArgs($params);
 
137
        }
 
138
    }
 
139
 
 
140
    /**
 
141
     * Resets the object to the initial state.
 
142
     */
 
143
    public function reset() {
 
144
        $this->classes = array();
 
145
        $this->instances = array();
 
146
    }
 
147
 
 
148
    /*** Autoloading Functions ***/
 
149
 
 
150
    /**
 
151
     * Starts/stops autoloader.
 
152
     *
 
153
     * @param bool $enabled Enable/disable autoloading
 
154
     * @param mixed $dirs Autoload directories
 
155
     */
 
156
    public static function autoload($enabled = true, $dirs = array()) {
 
157
        if ($enabled) {
 
158
            spl_autoload_register(array(__CLASS__, 'loadClass'));
 
159
        }
 
160
        else {
 
161
            spl_autoload_unregister(array(__CLASS__, 'loadClass'));
 
162
        }
 
163
 
 
164
        if (!empty($dirs)) {
 
165
            self::addDirectory($dirs);
 
166
        }
 
167
    }
 
168
 
 
169
    /**
 
170
     * Autoloads classes.
 
171
     *
 
172
     * @param string $class Class name
 
173
     */
 
174
    public static function loadClass($class) {
 
175
        $class_file = str_replace(array('\\', '_'), '/', $class).'.php';
 
176
 
 
177
        foreach (self::$dirs as $dir) {
 
178
            $file = $dir.'/'.$class_file;
 
179
            if (file_exists($file)) {
 
180
                require $file;
 
181
                return;
 
182
            }
 
183
        }
 
184
    }
 
185
 
 
186
    /**
 
187
     * Adds a directory for autoloading classes.
 
188
     *
 
189
     * @param mixed $dir Directory path
 
190
     */
 
191
    public static function addDirectory($dir) {
 
192
        if (is_array($dir) || is_object($dir)) {
 
193
            foreach ($dir as $value) {
 
194
                self::addDirectory($value);
 
195
            }
 
196
        }
 
197
        else if (is_string($dir)) {
 
198
            if (!in_array($dir, self::$dirs)) self::$dirs[] = $dir;
 
199
        }
 
200
    }
 
201
}