Completed
Push — 3.0 ( fea5eb...c29f0e )
by Vermeulen
02:17
created

Application::getDeclaredOptions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace BFW;
4
5
use \Exception;
6
use \BFW\Core\AppSystems\SystemInterface;
7
8
/**
9
 * Application class
10
 * Manage all BFW application
11
 * Load and init components, modules, ...
12
 */
13
class Application
14
{
15
    /**
16
     * @const ERR_CALL_UNKNOWN_METHOD Exception code if __call is called with
17
     * an unmanaged method
18
     */
19
    const ERR_CALL_UNKNOWN_METHOD = 1301001;
20
    
21
    /**
22
     * @const ERR_CALL_UNKNOWN_PROPERTY Exception code if __call is called with
23
     * an unmanaged property
24
     */
25
    const ERR_CALL_UNKNOWN_PROPERTY = 1301002;
26
    
27
    /**
28
     * @var \BFW\Application|null $instance Application instance (Singleton)
29
     */
30
    protected static $instance = null;
31
    
32
    /**
33
     * @var \BFW\Core\AppSystems\SystemInterface[] $coreSystemList A list of
34
     * all core system to init and run
35
     */
36
    protected $coreSystemList = [];
37
    
38
    /**
39
     * @var array $declaredOptions All options passed to initSystems method
40
     */
41
    protected $declaredOptions = [];
42
    
43
    /**
44
     * @var \BFW\RunTasks|null All method tu exec during run
45
     */
46
    protected $runTasks;
47
48
    /**
49
     * Constructor
50
     * Init output buffering
51
     * Declare core systems
52
     * Set UTF-8 header
53
     * 
54
     * protected for Singleton pattern
55
     */
56
    protected function __construct()
57
    {
58
        //Start the output buffering
59
        ob_start();
60
        
61
        $this->defineCoreSystemList();
62
63
        //Defaut http header. Define here add possiblity to override him
64
        header('Content-Type: text/html; charset=utf-8');
65
        
66
        //Default charset to UTF-8. Define here add possiblity to override him
67
        ini_set('default_charset', 'UTF-8');
68
    }
69
70
    /**
71
     * Get the Application instance (Singleton pattern)
72
     * 
73
     * @return \BFW\Application The current instance of this class
74
     */
75 View Code Duplication
    public static function getInstance()
76
    {
77
        if (self::$instance === null) {
78
            $calledClass = get_called_class(); //Autorize extends this class
79
            self::$instance = new $calledClass;
80
        }
81
82
        return self::$instance;
83
    }
84
    
85
    /**
86
     * Getter accessor to property coreSystemList
87
     * 
88
     * @return \BFW\Core\AppSystems\SystemInterface[]
89
     */
90
    public function getCoreSystemList()
91
    {
92
        return $this->coreSystemList;
93
    }
94
    
95
    /**
96
     * Getter accessor to property declaredOptions
97
     * 
98
     * @return array
99
     */
100
    public function getDeclaredOptions()
101
    {
102
        return $this->declaredOptions;
103
    }
104
    
105
    /**
106
     * Getter accessor to property runTasks
107
     * 
108
     * @return \BFW\RunTasks|null
109
     */
110
    public function getRunTasks()
111
    {
112
        return $this->runTasks;
113
    }
114
    
115
    /**
116
     * PHP Magic method, called when we call an unexisting method
117
     * Only method getXXX are allowed.
118
     * The property should be a key (ucfirst for camelcase) of the array
119
     * coreSystemList.
120
     * Ex: getConfig() or getModuleList()
121
     * The value returned will be the returned value of the __invoke method
122
     * into the core system class called.
123
     * 
124
     * @param string $name The method name
125
     * @param array $arguments The argument passed to the method
126
     * 
127
     * @return mixed
128
     * 
129
     * @throws \Exception If the method is not allowed or if the property
130
     * not exist.
131
     */
132
    public function __call($name, $arguments)
133
    {
134
        $prefix = substr($name, 0, 3);
135
        
136
        if ($prefix !== 'get') {
137
            throw new Exception(
138
                'Unknown method '.$name,
139
                self::ERR_CALL_UNKNOWN_METHOD
140
            );
141
        }
142
        
143
        $property = lcfirst(substr($name, 3));
144
        if (!array_key_exists($property, $this->coreSystemList)) {
145
            throw new Exception(
146
                'Unknown property '.$property,
147
                self::ERR_CALL_UNKNOWN_PROPERTY
148
            );
149
        }
150
        
151
        return $this->coreSystemList[$property](...$arguments);
152
    }
153
    
154
    /**
155
     * Define the list of coreSystem to init and/or run.
156
     * 
157
     * @return void
158
     */
159
    protected function defineCoreSystemList()
160
    {
161
        $this->coreSystemList = [
1 ignored issue
show
Documentation Bug introduced by
It seems like array('options' => new \...stems\CtrlRouterLink()) of type array<string,object<BFW\...ems\\CtrlRouterLink>"}> is incompatible with the declared type array<integer,object<BFW...stems\SystemInterface>> of property $coreSystemList.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
162
            'options'        => new Core\AppSystems\Options,
163
            'constants'      => new Core\AppSystems\Constants,
164
            'composerLoader' => new Core\AppSystems\ComposerLoader,
165
            'subjectList'    => new Core\AppSystems\SubjectList,
166
            'config'         => new Core\AppSystems\Config,
167
            'monolog'        => new Core\AppSystems\Monolog,
168
            'request'        => new Core\AppSystems\Request,
169
            'session'        => new Core\AppSystems\Session,
170
            'errors'         => new Core\AppSystems\Errors,
171
            'memcached'      => new Core\AppSystems\Memcached,
172
            'moduleList'     => new Core\AppSystems\ModuleList,
173
            'cli'            => new Core\AppSystems\Cli,
174
            'ctrlRouterLink' => new Core\AppSystems\CtrlRouterLink
175
        ];
176
    }
177
    
178
    /**
179
     * Initialize all components
180
     * 
181
     * @param array $options Options passed to application
182
     * 
183
     * @return void
184
     */
185
    public function initSystems($options)
186
    {
187
        $this->declaredOptions = $options;
188
        $this->runTasks        = new \BFW\RunTasks([], 'BfwApp');
189
        
190
        foreach ($this->coreSystemList as $name => $coreSystem) {
191
            $this->initCoreSystem($name, $coreSystem);
192
            
193
            if ($name === 'subjectList') {
1 ignored issue
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $name (integer) and 'subjectList' (string) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
194
                $this->getSubjectList()->addSubject(
0 ignored issues
show
Documentation Bug introduced by
The method getSubjectList does not exist on object<BFW\Application>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
195
                    $this->runTasks,
196
                    'ApplicationTasks'
197
                );
198
            }
199
        }
200
        
201
        $this->getMonolog()
0 ignored issues
show
Documentation Bug introduced by
The method getMonolog does not exist on object<BFW\Application>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
202
            ->getLogger()
203
            ->debug('Framework initializing done.')
204
        ;
205
        
206
        return $this;
207
    }
208
    
209
    /**
210
     * Init all core system declared, only if they have not been already init.
211
     * If the system should be run, we add him to the runTasks object.
212
     * 
213
     * @param string $name The core system name
214
     * @param \BFW\Core\AppSystems\SystemInterface $coreSystem The core system
215
     * instance.
216
     * 
217
     * @return void
218
     */
219
    protected function initCoreSystem($name, SystemInterface $coreSystem)
220
    {
221
        if ($coreSystem->isInit() === true) {
222
            return;
223
        }
224
225
        $coreSystem->init();
226
        
227
        if ($coreSystem->toRun() === true) {
228
            $this->runTasks->addToRunSteps(
229
                $name,
230
                (object) [
231
                    'callback' => [$coreSystem, 'run']
232
                ]
233
            );
234
        }
235
    }
236
237
    /**
238
     * Run the application
239
     * 
240
     * @return void
241
     */
242
    public function run()
243
    {
244
        $this->getMonolog()->getLogger()->debug('running framework');
0 ignored issues
show
Documentation Bug introduced by
The method getMonolog does not exist on object<BFW\Application>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
245
        
246
        $this->runTasks->run();
247
        $this->runTasks->sendNotify('bfw_run_done');
248
    }
249
}
250