DetailViewWidget::__construct()   D
last analyzed

Complexity

Conditions 9
Paths 12

Size

Total Lines 40
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 40
c 0
b 0
f 0
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\Html;
9
10
/**
11
 * DetailViewWidget class file.
12
 *
13
 * @author Oleg Lunegov <[email protected]>
14
 * @link https://github.com/linpax/microphp-framework
15
 * @copyright Copyright (c) 2013 Oleg Lunegov
16
 * @license https://github.com/linpax/microphp-framework/blob/master/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
    /**
42
     * Redeclare constructor, generate keys and data
43
     *
44
     * @access public
45
     *
46
     * @param array $args Arguments
47
     *
48
     * @result void
49
     * @throws \Micro\base\Exception
50
     */
51
    public function __construct(array $args = [])
52
    {
53
        parent::__construct($args);
54
55
        if (empty($args['data'])) {
56
            throw new Exception('Argument "data" not initialized into DetailViewWidget');
57
        }
58
59
        switch (gettype($args['data'])) {
60
            case 'array':
61
                $this->data = (object)$args['data'];
62
                $this->keys = array_keys($args['data']);
63
                break;
64
65
            case 'object':
66
                if ($args['data'] instanceof IQuery) {
67
                    if ($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...
68
                        /** @var IModel $cls */
69
                        $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...
70
                        /** @noinspection PhpUndefinedFieldInspection */
71
                        $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...
72
                    } 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...
73
                        throw new Exception('Data query not set table or objectName');
74
                    }
75
                    $this->data = $args['data']->run();
76
                } elseif (is_subclass_of($args['data'], 'Micro\\Mvc\\Models\\Model')) {
77
                    $this->data = $args['data'];
78
                } else {
79
                    throw new Exception('Argument "model" not supported type into DetailViewWidget');
80
                }
81
                $this->keys = $this->data->getAttributes();
82
                break;
83
84
            default:
85
                throw new Exception('Argument "model" not supported type into DetailViewWidget');
86
        }
87
        if (empty($args['columns'])) {
88
            $this->columns = $this->keys;
89
        }
90
    }
91
92
    /**
93
     * Prepare selected rows
94
     *
95
     * @access public
96
     *
97
     * @return void
98
     * @throws Exception
99
     */
100
    public function init()
101
    {
102
        $result = [];
103
104
        // обходим заданные параметры
105
        foreach ($this->columns AS $key => $val) {
106
            $data = [];
107
108
            // если параметр число и вал строка - это ключ
109
            if (is_int($key) && is_string($val)) {
110
                $column = $val;
111
                // если параметр строка и вал массив - is good
112
            } elseif (is_string($key) && is_array($val)) {
113
                $column = $key;
114
            } else {
115
                throw new Exception('Unknown `data` format into DetailViewWidget');
116
            }
117
118
            $result[] = [
119
                'title' => !empty($data['title']) ? $data['title'] : ucfirst(method_exists($this->data,
120
                    'getLabel') ? $this->data->getLabel($column) : $column),
121
                'type' => !empty($data['type']) ? $data['type'] : 'text',
122
                'value' => !empty($data['value']) ? $data['value'] : $this->data->{$column}
123
            ];
124
        }
125
126
        $this->columns = $result;
127
    }
128
129
    /**
130
     * Run drawing
131
     *
132
     * @access public
133
     *
134
     * @return void
135
     */
136
    public function run()
137
    {
138
        $result = Html::openTag('dl', $this->attributes);
139
140
        foreach ($this->columns AS $key => $val) {
141
            $result .= Html::openTag('dt', $this->attributesElement);
142
            $result .= $val['title'];
143
            $result .= Html::closeTag('dt');
144
            $result .= Html::openTag('dd', $this->attributesValue);
145
146
            $buffer = '';
147
            /** @noinspection DegradedSwitchInspection */
148
            switch ($val['type']) {
149
                case 'raw':
150
                    $buffer .= eval('$data = $this->data; 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...
151
                    break;
152
153
                default:
154
                    if (property_exists($this->data, $val['value'])) {
155
                        $buffer .= htmlspecialchars($this->data->{$val['value']});
156
                    } else {
157
                        $buffer .= htmlspecialchars($val['value']);
158
                    }
159
            }
160
161
            $result .= (strlen($buffer) ? $buffer : '&nbsp;').Html::closeTag('dd');
162
        }
163
164
        echo $result, Html::closeTag('dl');
165
    }
166
}
167