Completed
Push — master ( 9456a3...652b9a )
by Markus
06:38
created

Context::getModel()   F

Complexity

Conditions 17
Paths 528

Size

Total Lines 98
Code Lines 43

Duplication

Lines 17
Ratio 17.35 %

Importance

Changes 0
Metric Value
cc 17
eloc 43
nc 528
nop 3
dl 17
loc 98
rs 2.8344
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
// +---------------------------------------------------------------------------+
4
// | This file is part of the Agavi package.                                   |
5
// | Copyright (c) 2005-2011 the Agavi Project.                                |
6
// | Based on the Mojavi3 MVC Framework, Copyright (c) 2003-2005 Sean Kerr.    |
7
// |                                                                           |
8
// | For the full copyright and license information, please view the LICENSE   |
9
// | file that was distributed with this source code. You can also view the    |
10
// | LICENSE file online at http://www.agavi.org/LICENSE.txt                   |
11
// |   vi: set noexpandtab:                                                    |
12
// |   Local Variables:                                                        |
13
// |   indent-tabs-mode: t                                                     |
14
// |   End:                                                                    |
15
// +---------------------------------------------------------------------------+
16
17
namespace Agavi\Core;
18
19
use Agavi\Config\ConfigCache;
20
use Agavi\Database\DatabaseManager;
21
use Agavi\Exception\AgaviException;
22
use Agavi\Exception\AutoloadException;
23
use Agavi\Exception\DatabaseException;
24
use Agavi\Exception\DisabledModuleException;
25
use Agavi\Config\Config;
26
use Agavi\Dispatcher\Dispatcher;
27
use Agavi\Logging\LoggerManager;
28
use Agavi\Model\Model;
29
use Agavi\Request\Request;
30
use Agavi\Routing\Routing;
31
use Agavi\Storage\Storage;
32
use Agavi\Translation\TranslationManager;
33
use Agavi\User\User;
34
use Agavi\Util\Toolkit;
35
36
/**
37
 * Context provides information about the current application context,
38
 * such as the module and controller names and the module directory.
39
 * It also serves as a gateway to the core pieces of the framework, allowing
40
 * objects with access to the context, to access other useful objects such as
41
 * the current Dispatcher, request, user, database manager etc.
42
 *
43
 * @package    agavi
44
 * @subpackage core
45
 *
46
 * @author     Sean Kerr <[email protected]>
47
 * @author     Mike Vincent <[email protected]>
48
 * @author     David Zülke <[email protected]>
49
 * @copyright  Authors
50
 * @copyright  The Agavi Project
51
 *
52
 * @since      0.9.0
53
 *
54
 * @version    $Id$
55
 */
56
57
class Context
58
{
59
    /**
60
     * @var        string The name of the Context.
61
     */
62
    protected $name = '';
63
    
64
    /**
65
     * @var        Dispatcher A Dispatcher instance.
66
     */
67
    protected $dispatcher = null;
68
    
69
    /**
70
     * @var        array An array of class names for frequently used factories.
71
     */
72
    protected $factories = array(
73
        'dispatch_filter' => null,
74
        'execution_container' => null,
75
        'execution_filter' => null,
76
        'filter_chain' => null,
77
        'response' => null,
78
        'security_filter' => null,
79
        'validation_manager' => null,
80
    );
81
    
82
    /**
83
     * @var        DatabaseManager A DatabaseManager instance.
84
     */
85
    protected $databaseManager = null;
86
    
87
    /**
88
     * @var        LoggerManager A LoggerManager instance.
89
     */
90
    protected $loggerManager = null;
91
    
92
    /**
93
     * @var        Request A Request instance.
94
     */
95
    protected $request = null;
96
    
97
    /**
98
     * @var        Routing A Routing instance.
99
     */
100
    protected $routing = null;
101
    
102
    /**
103
     * @var        Storage A Storage instance.
104
     */
105
    protected $storage = null;
106
    
107
    /**
108
     * @var        TranslationManager A TranslationManager instance.
109
     */
110
    protected $translationManager = null;
111
    
112
    /**
113
     * @var        User A User instance.
114
     */
115
    protected $user = null;
116
    
117
    /**
118
     * @var        array The array used for the shutdown sequence.
119
     */
120
    protected $shutdownSequence = array();
121
    
122
    /**
123
     * @var        array An array of Context instances.
124
     */
125
    protected static $instances = array();
126
    
127
    /**
128
     * @var        array An array of SingletonModel instances.
129
     */
130
    protected $singletonModelInstances = array();
131
132
    /**
133
     * Clone method, overridden to prevent cloning, there can be only one.
134
     *
135
     * @author     Mike Vincent <[email protected]>
136
     * @since      0.9.0
137
     */
138
    public function __clone()
139
    {
140
        trigger_error('Cloning a Context instance is not allowed.', E_USER_ERROR);
141
    }
142
143
    /**
144
     * Constructor method, intentionally made protected so the context cannot be
145
     * created directly.
146
     *
147
     * @param      string $name The name of this context.
148
     *
149
     * @author     David Zülke <[email protected]>
150
     * @author     Mike Vincent <[email protected]>
151
     * @since      0.9.0
152
     */
153
    protected function __construct($name)
154
    {
155
        $this->name = $name;
156
    }
157
158
    /**
159
     * __toString overload, returns the name of the Context.
160
     *
161
     * @return     string The context name.
162
     *
163
     * @see        Context::getName()
164
     *
165
     * @author     David Zülke <[email protected]>
166
     * @since      0.11.0
167
     */
168
    public function __toString()
169
    {
170
        return $this->getName();
171
    }
172
    
173
    /**
174
     * Get information on a frequently used class.
175
     *
176
     * @param      string $for The factory identifier.
177
     *
178
     * @return     array An associative array (keys 'class' and 'parameters').
179
     *
180
     * @author     David Zülke <[email protected]>
181
     * @since      0.11.0
182
     */
183
    public function getFactoryInfo($for)
184
    {
185
        if (isset($this->factories[$for])) {
186
            return $this->factories[$for];
187
        }
188
    }
189
    
190
    /**
191
     * Set information on a frequently used class.
192
     *
193
     * @param      string $for The factory identifier.
194
     * @param      array $info An associative array (keys 'class' and 'parameters').
195
     *
196
     * @author     Felix Gilcher <[email protected]>
197
     * @since      1.0.1
198
     */
199
    public function setFactoryInfo($for, array $info)
200
    {
201
        $this->factories[$for] = $info;
202
    }
203
204
    /**
205
     * Factory for frequently used classes from factories.xml
206
     *
207
     * @param      string $for The factory identifier.
208
     *
209
     * @return     mixed An instance, already initialized with parameters.
210
     *
211
     * @throws     AgaviException If no such identifier exists.
212
     *
213
     * @author     David Zülke <[email protected]>
214
     * @since      1.0.0
215
     */
216
    public function createInstanceFor($for)
217
    {
218
        $info = $this->getFactoryInfo($for);
219
        if (null === $info) {
220
            throw new AgaviException(sprintf('No factory info for "%s"', $for));
221
        }
222
        
223
        $class = new $info['class']();
224
        $class->initialize($this, $info['parameters']);
225
        return $class;
226
    }
227
228
    /**
229
     * Retrieve the Dispatcher.
230
     *
231
     * @return     Dispatcher The current Dispatcher implementation instance.
232
     *
233
     * @author     Sean Kerr <[email protected]>
234
     * @since      0.9.0
235
     */
236
    public function getDispatcher()
237
    {
238
        return $this->dispatcher;
239
    }
240
241
    /**
242
     * Retrieve a database connection from the database manager.
243
     *
244
     * This is a shortcut to manually getting a connection from an existing
245
     * database implementation instance.
246
     *
247
     * If the core.use_database setting is off, this will return null.
248
     *
249
     * @param      string $name A database name.
250
     *
251
     * @return     mixed A database connection.
252
     *
253
     * @throws     DatabaseException If the requested database name
254
     *                                           does not exist.
255
     *
256
     * @author     Sean Kerr <[email protected]>
257
     * @since      0.9.0
258
     */
259
    public function getDatabaseConnection($name = null)
260
    {
261
        if ($this->databaseManager !== null) {
262
            return $this->databaseManager->getDatabase($name)->getConnection();
263
        }
264
    }
265
266
    /**
267
     * Retrieve the database manager.
268
     *
269
     * @return     DatabaseManager The current DatabaseManager instance.
270
     *
271
     * @author     Sean Kerr <[email protected]>
272
     * @since      0.9.0
273
     */
274
    public function getDatabaseManager()
275
    {
276
        return $this->databaseManager;
277
    }
278
279
    /**
280
     * Retrieve the Context instance.
281
     *
282
     * If you don't supply a profile name this will try to return the context
283
     * specified in the <kbd>core.default_context</kbd> setting.
284
     *
285
     * @param      string $profile A name corresponding to a section of the config
286
     *
287
     * @return     Context An context instance initialized with the
288
     *                     settings of the requested context name
289
     *
290
     * @author     Dominik del Bondio <[email protected]>
291
     * @author     David Zülke <[email protected]>
292
     * @author     Mike Vincent <[email protected]>
293
     * @since      0.9.0
294
     */
295
    public static function getInstance($profile = null)
296
    {
297
        try {
298
            if ($profile === null) {
299
                $profile = Config::get('core.default_context');
300
                if ($profile === null) {
301
                    throw new AgaviException('You must supply a context name to Context::getInstance() or set the name of the default context to be used in the configuration directive "core.default_context".');
302
                }
303
            }
304
            $profile = strtolower($profile);
305
            if (!isset(self::$instances[$profile])) {
306
                $class = Config::get('core.context_implementation', get_called_class());
307
                self::$instances[$profile] = new $class($profile);
308
                self::$instances[$profile]->initialize();
309
            }
310
            return self::$instances[$profile];
311
        } catch (\Exception $e) {
312
            AgaviException::render($e);
313
        }
314
    }
315
    
316
    /**
317
     * Retrieve the LoggerManager
318
     *
319
     * @return     LoggerManager The current LoggerManager implementation
320
     *                           instance.
321
     *
322
     * @author     David Zülke <[email protected]>
323
     * @since      0.11.0
324
     */
325
    public function getLoggerManager()
326
    {
327
        return $this->loggerManager;
328
    }
329
330
    /**
331
     * (re)Initialize the Context instance.
332
     *
333
     * @author     Dominik del Bondio <[email protected]>
334
     * @author     David Zülke <[email protected]>
335
     * @author     Mike Vincent <[email protected]>
336
     * @since      0.10.0
337
     */
338
    public function initialize()
339
    {
340
        try {
341
            include(ConfigCache::checkConfig(Config::get('core.config_dir') . '/factories.xml', $this->name));
342
        } catch (\Exception $e) {
343
            AgaviException::render($e, $this);
344
        }
345
        
346
        register_shutdown_function(array($this, 'shutdown'));
347
    }
348
    
349
    /**
350
     * Shut down this Context and all related factories.
351
     *
352
     * @author     David Zülke <[email protected]>
353
     * @since      0.11.0
354
     */
355
    public function shutdown()
356
    {
357
        foreach ($this->shutdownSequence as $object) {
358
            $object->shutdown();
359
        }
360
    }
361
    
362
    /**
363
     * Retrieve a Model implementation instance.
364
     *
365
     * @param      string $modelName A model name.
366
     * @param      string $moduleNameA module name, if the requested model is a module model,
0 ignored issues
show
Documentation introduced by
There is no parameter named $moduleNameA. Did you maybe mean $moduleName?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
367
     *                    or null for global models.
368
     * @param      array  $parameters An array of parameters to be passed to initialize() or
369
     *                    the constructor.
370
     *
371
     * @return     Model A Model implementation instance.
372
     *
373
     * @throws     AutoloadException if class is ultimately not found.
374
     *
375
     *
376
     * @author     David Zülke <[email protected]>
377
     * @since      0.11.0
378
     */
379
    public function getModel($modelName, $moduleName = null, array $parameters = null)
380
    {
381
382
        $modelName = $origModelName = str_replace('.', '\\', $modelName);
383
384
        // We have a namespace, get the name
385 View Code Duplication
        if (strpos($modelName, '\\') !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
386
            // Remove any submodel-references
387
            $modelName = substr($modelName, strrpos($modelName, '\\')+1);
388
        }
389
        $file = null;
390
        $rc = null;
391
392
        // We have a namespace, get the name
393 View Code Duplication
        if (strpos($modelName, '\\') !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
394
            $modelName = substr($modelName, strrpos($modelName, '\\')+1);
395
        }
396
397
        $ns = Config::get('app.namespace');
398
399
        $class = $modelName;
400
401
        if ($moduleName === null) {
402
403
            // If we have a base namespace defined, add it to the model name
404
            if ($ns)
405
                $class = $ns . '\\Models\\' . $origModelName . 'Model';
406
407
            // global model
408
            // let's try to autoload that baby
409 View Code Duplication
            if (!class_exists($class)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
410
                // it's not there. the hunt is on
411
                $file = Config::get('core.model_dir') . '/' . str_replace('\\', DIRECTORY_SEPARATOR, $origModelName) . 'Model.class.php';
412
                require($file);
413
            }
414
415
        } else {
416
417
            try {
418
                $this->dispatcher->initializeModule($moduleName);
419
            } catch (DisabledModuleException $e) {
420
                // swallow, this will load the modules autoload but throw an exception
421
                // if the module is disabled.
422
            }
423
424
            if ($ns)
425
                $class = $ns . '\\Modules\\' . $moduleName . '\\Models\\' . $origModelName . 'Model';
426
427
            // module model
428
            // let's try to autoload the baby
429 View Code Duplication
            if (!class_exists($class)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
430
                // it's not there. the hunt is on
431
                $file = Config::get('core.module_dir') . '/' . $moduleName . '/models/' . str_replace('\\', DIRECTORY_SEPARATOR, $origModelName) . 'Model.class.php';
432
                require($file);
433
            }
434
        }
435
436
        if (!class_exists($class)) {
437
            // it's not there.
438
            throw new AgaviException(sprintf("Couldn't find class %s for Model %s in file %s", $class, $modelName, $file));
439
        }
440
        
441
        // so if we're here, we found something, right? good.
442
        
443
        $rc = new \ReflectionClass($class);
444
        
445
        if ($rc->implementsInterface('Agavi\\Model\\SingletonModelInterface')) {
446
            // it's a singleton
447
            if (!isset($this->singletonModelInstances[$class])) {
448
                // no instance yet, so we create one
449
                
450
                if ($parameters === null || $rc->getConstructor() === null) {
451
                    // it has an initialize() method, or no parameters were given, so we don't hand arguments to the constructor
452
                    $this->singletonModelInstances[$class] = new $class();
453
                } else {
454
                    // we use this approach so we can pass constructor params or if it doesn't have an initialize() method
455
                    $this->singletonModelInstances[$class] = $rc->newInstanceArgs($parameters);
456
                }
457
            }
458
            $model = $this->singletonModelInstances[$class];
459
        } else {
460
            // create an instance
461
            if ($parameters === null || $rc->getConstructor() === null) {
462
                // it has an initialize() method, or no parameters were given, so we don't hand arguments to the constructor
463
                $model = new $class();
464
            } else {
465
                // we use this approach so we can pass constructor params or if it doesn't have an initialize() method
466
                $model = $rc->newInstanceArgs($parameters);
467
            }
468
        }
469
        
470
        if (is_callable(array($model, 'initialize'))) {
471
            // pass the constructor params again. dual use for the win
472
            $model->initialize($this, (array) $parameters);
473
        }
474
        
475
        return $model;
476
    }
477
478
    /**
479
     * Retrieve the name of this Context.
480
     *
481
     * @return     string A context name.
482
     *
483
     * @author     David Zülke <[email protected]>
484
     * @since      0.11.0
485
     */
486
    public function getName()
487
    {
488
        return $this->name;
489
    }
490
    
491
    /**
492
     * Retrieve the request.
493
     *
494
     * @return     Request The current Request implementation instance.
495
     *
496
     * @author     Sean Kerr <[email protected]>
497
     * @since      0.9.0
498
     */
499
    public function getRequest()
500
    {
501
        return $this->request;
502
    }
503
504
    /**
505
     * Retrieve the routing.
506
     *
507
     * @return     Routing The current Routing implementation instance.
508
     *
509
     * @author     Dominik del Bondio <[email protected]>
510
     * @since      0.11.0
511
     */
512
    public function getRouting()
513
    {
514
        return $this->routing;
515
    }
516
517
    /**
518
     * Retrieve the storage.
519
     *
520
     * @return     Storage The current Storage implementation instance.
521
     *
522
     * @author     Sean Kerr <[email protected]>
523
     * @since      0.9.0
524
     */
525
    public function getStorage()
526
    {
527
        return $this->storage;
528
    }
529
530
    /**
531
     * Retrieve the translation manager.
532
     *
533
     * @return     TranslationManager The current TranslationManager
534
     *                                     implementation instance.
535
     *
536
     * @author     Dominik del Bondio <[email protected]>
537
     * @since      0.11.0
538
     */
539
    public function getTranslationManager()
540
    {
541
        return $this->translationManager;
542
    }
543
544
    /**
545
     * Retrieve the user.
546
     *
547
     * @return     User The current User implementation instance.
548
     *
549
     * @author     Sean Kerr <[email protected]>
550
     * @since      0.9.0
551
     */
552
    public function getUser()
553
    {
554
        return $this->user;
555
    }
556
}
557