Completed
Push — master ( 99527b...ffb88b )
by Oleg
03:03
created

Controller::getActionClassByName()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 16
rs 8.8571
cc 5
eloc 9
nc 3
nop 1
1
<?php /** MicroController */
2
3
namespace Micro\Mvc\Controllers;
4
5
use Micro\Base\Exception;
6
use Micro\Base\IContainer;
7
use Micro\Mvc\Module;
8
use Micro\Web\IResponse;
9
use Micro\Web\Response;
10
11
/**
12
 * Class Controller
13
 *
14
 * @author Oleg Lunegov <[email protected]>
15
 * @link https://github.com/lugnsk/micro
16
 * @copyright Copyright &copy; 2013 Oleg Lunegov
17
 * @license /LICENSE
18
 * @package Micro
19
 * @subpackage Mvc\Controllers
20
 * @version 1.0
21
 * @since 1.0
22
 * @abstract
23
 */
24
abstract class Controller implements IController
25
{
26
    /** @var Module $module */
27
    public $module;
28
    /** @var IResponse $response Response HTTP data */
29
    public $response;
30
    /** @var IContainer $container */
31
    protected $container;
32
33
    /**
34
     * Constructor controller
35
     *
36
     * @access public
37
     *
38
     * @param IContainer $container
39
     * @param string $modules
40
     *
41
     * @result void
42
     */
43
    public function __construct(IContainer $container, $modules = '')
44
    {
45
        $this->container = $container;
46
47
        // if module defined
48
        if ($modules) {
49
            $modules   = str_replace('\\', '/', $modules);
50
            $app       = $this->container->kernel->getAppDir();
0 ignored issues
show
Bug introduced by
Accessing kernel on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
51
            $path      = $app . $modules . '/' . ucfirst(basename($modules)) . 'Module.php';
52
            $className = substr(str_replace('/', '\\', str_replace($app, 'App', $path)), 0, -4);
53
54
            // search module class
55
            if (file_exists($path) && class_exists($className) && is_subclass_of($className, '\Micro\Mvc\Module')) {
56
                $this->module = new $className($this->container);
57
            }
58
        }
59
60
        if (!$this->response = $this->container->response) {
0 ignored issues
show
Bug introduced by
Accessing response on the interface Micro\Base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
61
            $this->response = new Response;
62
        }
63
    }
64
65
    /**
66
     * Apply filters
67
     *
68
     * @access public
69
     *
70
     * @param string $action current action name
71
     * @param bool $isPre is pre or post
72
     * @param array $filters defined filters
73
     * @param string $data data to parse
74
     *
75
     * @return null|string
76
     * @throws Exception
77
     */
78
    public function applyFilters($action, $isPre = true, array $filters = [], $data = null)
79
    {
80
        if (!$filters) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $filters of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
81
            return $data;
82
        }
83
84
        foreach ($filters as $filter) {
85
            if (empty($filter['class']) || !class_exists($filter['class'])) {
86
                continue;
87
            }
88
89
            if (empty($filter['actions']) || !in_array($action, $filter['actions'], true)) {
90
                continue;
91
            }
92
93
            /** @var \Micro\Filter\IFilter $_filter */
94
            $_filter = new $filter['class']($action, $this->container);
95
96
            $res = $isPre ? $_filter->pre($filter) : $_filter->post($filter + ['data' => $data]);
97
            if (!$res) {
98
                if (!empty($_filter->result['redirect'])) {
0 ignored issues
show
Bug introduced by
Accessing result on the interface Micro\Filter\IFilter suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
99
                    header('Location: ' . $_filter->result['redirect']);
0 ignored issues
show
Bug introduced by
Accessing result on the interface Micro\Filter\IFilter suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
100
101
                    die();
0 ignored issues
show
Coding Style Compatibility introduced by
The method applyFilters() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
102
                }
103
                throw new Exception($_filter->result['message']);
0 ignored issues
show
Bug introduced by
Accessing result on the interface Micro\Filter\IFilter suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
104
            }
105
            $data = $res;
106
        }
107
108
        return $data;
109
    }
110
111
    /**
112
     * Get action class by name
113
     *
114
     * @access public
115
     *
116
     * @param string $name action name
117
     *
118
     * @return bool
119
     */
120
    public function getActionClassByName($name)
121
    {
122
        if (method_exists($this, 'actions')) {
123
            $actions = $this->actions();
0 ignored issues
show
Bug introduced by
The method actions() does not exist on Micro\Mvc\Controllers\Controller. Did you maybe mean action()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
124
125
            if (
126
                !empty($actions[$name]) &&
127
                class_exists($actions[$name]) &&
128
                is_subclass_of($actions[$name], '\Micro\Mvc\Action')
129
            ) {
130
                return $actions[$name];
131
            }
132
        }
133
134
        return false;
135
    }
136
}
137