Completed
Push — master ( 579af5...b29473 )
by Oleg
07:53
created

DetailViewWidget::__construct()   D

Complexity

Conditions 9
Paths 12

Size

Total Lines 39
Code Lines 27

Duplication

Lines 7
Ratio 17.95 %
Metric Value
dl 7
loc 39
rs 4.909
cc 9
eloc 27
nc 12
nop 1
1
<?php /** MicroDetailViewWidget */
2
namespace Micro\Widget;
3
4
use Micro\Base\Exception;
5
use Micro\Mvc\Models\IModel;
6
use Micro\Mvc\Models\IQuery;
7
use Micro\Mvc\Widget;
8
use Micro\Web\Html;
9
10
/**
11
 * DetailViewWidget class file.
12
 *
13
 * @author Oleg Lunegov <[email protected]>
14
 * @link https://github.com/lugnsk/micro
15
 * @copyright Copyright &copy; 2013 Oleg Lunegov
16
 * @license /LICENSE
17
 * @package Micro
18
 * @subpackage Widget
19
 * @version 1.0
20
 * @since 1.0
21
 */
22
class DetailViewWidget extends Widget
23
{
24
    /** @var array $columns Rendered columns */
25
    public $columns;
26
    /** @var array $attributes attributes for dl */
27
    public $attributes = [];
28
    /** @var array $attributesElement attributes for dt */
29
    public $attributesElement = [];
30
    /** @var array $attributesValue attributes for dd */
31
    public $attributesValue = [];
32
    /** @var array $attributeLabels labels for attributes */
33
    public $attributeLabels = [];
34
35
    /** @var array $keys Data keys */
36
    protected $keys;
37
    /** @var mixed $data Data source */
38
    protected $data;
39
40
    /**
41
     * Redeclare constructor, generate keys and data
42
     *
43
     * @access public
44
     *
45
     * @param array $args Arguments
46
     *
47
     * @result void
48
     * @throws \Micro\base\Exception
49
     */
50
    public function __construct(array $args = [])
51
    {
52
        parent::__construct($args);
53
54
        if (empty($args['data'])) {
55
            throw new Exception('Argument "data" not initialized into DetailViewWidget');
56
        }
57
58
        switch (gettype($args['data'])) {
59
            case 'array':
60
                $this->data = (object)$args['data'];
61
                $this->keys = array_keys($args['data']);
62
                break;
63
64
            case 'object':
65
                if ($args['data'] instanceof IQuery) {
66 View Code Duplication
                    if ($args['data']->objectName) {
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...
Bug introduced by
Accessing objectName on the interface Micro\Mvc\Models\IQuery 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...
67
                        /** @var IModel $cls */
68
                        $cls = $args['data']->objectName;
0 ignored issues
show
Bug introduced by
Accessing objectName on the interface Micro\Mvc\Models\IQuery 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...
69
                        $args['data']->table = $cls::tableName();
0 ignored issues
show
Bug introduced by
Accessing table on the interface Micro\Mvc\Models\IQuery 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...
70
                    } elseif (!$args['data']->table) {
0 ignored issues
show
Bug introduced by
Accessing table on the interface Micro\Mvc\Models\IQuery 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...
71
                        throw new Exception('Data query not set table or objectName');
72
                    }
73
                    $this->data = $args['data']->run();
74
                } elseif (is_subclass_of($args['data'], 'Micro\\Mvc\\Models\\Model')) {
75
                    $this->data = $args['data'];
76
                } else {
77
                    throw new Exception('Argument "model" not supported type into DetailViewWidget');
78
                }
79
                $this->keys = $this->data->getAttributes();
80
                break;
81
82
            default:
83
                throw new Exception('Argument "model" not supported type into DetailViewWidget');
84
        }
85
        if (empty($args['columns'])) {
86
            $this->columns = $this->keys;
87
        }
88
    }
89
90
    /**
91
     * Prepare selected rows
92
     *
93
     * @access public
94
     *
95
     * @return void
96
     * @throws Exception
97
     */
98
    public function init()
99
    {
100
        $result = [];
101
102
        // обходим заданные параметры
103
        foreach ($this->columns AS $key => $val) {
104
            $data = [];
105
106
            // если параметр число и вал строка - это ключ
107
            if (is_int($key) && is_string($val)) {
108
                $column = $val;
109
                // если параметр строка и вал массив - is good
110
            } elseif (is_string($key) && is_array($val)) {
111
                $column = $key;
112
            } else {
113
                throw new Exception('Unknown `data` format into DetailViewWidget');
114
            }
115
116
            $result[] = [
117
                'title' => !empty($data['title']) ? $data['title'] : ucfirst(method_exists($this->data,
118
                    'getLabel') ? $this->data->getLabel($column) : $column),
119
                'type' => !empty($data['type']) ? $data['type'] : 'text',
120
                'value' => !empty($data['value']) ? $data['value'] : $this->data->{$column}
121
            ];
122
        }
123
124
        $this->columns = $result;
125
    }
126
127
    /**
128
     * Run drawing
129
     *
130
     * @access public
131
     *
132
     * @return void
133
     */
134
    public function run()
135
    {
136
        $result = Html::openTag('dl', $this->attributes);
137
138
        foreach ($this->columns AS $key => $val) {
139
            $result .= Html::openTag('dt', $this->attributesElement);
140
            $result .= $val['title'];
141
            $result .= Html::closeTag('dt');
142
            $result .= Html::openTag('dd', $this->attributesValue);
143
144
            $buffer = '';
145
            /** @noinspection DegradedSwitchInspection */
146
            switch ($val['type']) {
147
                case 'raw':
148
                    /** @noinspection OnlyWritesOnParameterInspection */
149
                    /** @noinspection PhpUnusedLocalVariableInspection */
150
                    $data = $this->data; // for eval
0 ignored issues
show
Unused Code introduced by
$data is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
151
                    $buffer .= eval('return ' . $val['value']);
0 ignored issues
show
Coding Style introduced by
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
152
                    break;
153
154
                default:
155
                    if (property_exists($this->data, $val['value'])) {
156
                        $buffer .= htmlspecialchars($this->data->{$val['value']});
157
                    } else {
158
                        $buffer .= htmlspecialchars($val['value']);
159
                    }
160
            }
161
162
            $result .= (strlen($buffer) ? $buffer : '&nbsp;') . Html::closeTag('dd');
163
        }
164
165
        echo $result, Html::closeTag('dl');
166
    }
167
}
168