Completed
Push — master ( 1f06a4...f2af88 )
by Nikolas
04:02
created

MultiField::toString()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 9.4286
cc 2
eloc 5
nc 2
nop 1
1
<?php
2
namespace rtens\domin\delivery\web\fields;
3
4
use rtens\domin\delivery\FieldRegistry;
5
use rtens\domin\Parameter;
6
use rtens\domin\delivery\web\Element;
7
use rtens\domin\delivery\web\HeadElements;
8
use rtens\domin\delivery\web\WebField;
9
use watoki\collections\Map;
10
use watoki\reflect\Type;
11
use watoki\reflect\type\ClassType;
12
use watoki\reflect\type\MultiType;
13
14
class MultiField implements WebField {
15
16
    /** @var FieldRegistry */
17
    private $fields;
18
19
    /**
20
     * @param FieldRegistry $fields
21
     */
22
    public function __construct(FieldRegistry $fields) {
23
        $this->fields = $fields;
24
    }
25
26
    /**
27
     * @param Parameter $parameter
28
     * @return bool
29
     */
30
    public function handles(Parameter $parameter) {
31
        return $parameter->getType() instanceof MultiType;
32
    }
33
34
    /**
35
     * @param Parameter $parameter
36
     * @param Map $serialized
37
     * @return mixed
38
     */
39
    public function inflate(Parameter $parameter, $serialized) {
40
        foreach ($this->getTypes($parameter) as $i => $type) {
41
            if ($serialized->has("multi-$i")) {
42
                $optionParameter = new Parameter($parameter->getName(), $type);
43
                return $this->getField($optionParameter)->inflate($optionParameter, $serialized["multi-$i"]);
44
            }
45
        }
46
        return null;
47
    }
48
49
    /**
50
     * @param Parameter $parameter
51
     * @param mixed|null $value
52
     * @return string
53
     */
54
    public function render(Parameter $parameter, $value) {
55
        $id = str_replace(['[', ']'], '-', $parameter->getName());
56
57
        return implode("\n", array_merge([
58
            new Element('select', [
59
                'class' => 'form-control form-group',
60
                'onchange' => "$(this).next().hide().appendTo('body'); $('#' + $(this).val()).show().insertAfter($(this));"
61
            ], $this->getOptions($parameter, $value, $id))
62
        ], $this->renderOptions($parameter, $value, $id)));
63
    }
64
65
    private function renderOptions(Parameter $parameter, $value, $id) {
66
        $fields = [];
67
        foreach ($this->getTypes($parameter) as $i => $type) {
68
            $optionParameter = new Parameter($parameter->getName() . "[multi-$i]", $type);
69
            $selected = is_null($value) && $i == 0 || $type->is($value);
70
            $fields[] = new Element('div', ['class' => 'multi-control' . ($selected ? '' : ' not-selected'), 'id' => "$id-multi-option-$i"], [
71
                $this->getField($optionParameter)->render($optionParameter, $type->is($value) ? $value : null)
72
            ]);
73
        }
74
        return $fields;
75
    }
76
77
    /**
78
     * @param Parameter $parameter
79
     * @return array|Element[]
80
     */
81
    public function headElements(Parameter $parameter) {
82
        $ownElements = [
83
            HeadElements::jquery(),
84
            new Element('script', [], [
85
                "$(function () {
86
                    $('.multi-control.not-selected').hide().appendTo('body');
87
                });"
88
            ])
89
        ];
90
91
        foreach ($this->getTypes($parameter) as $i => $type) {
92
            $optionParameter = new Parameter($parameter->getName(), $type);
93
            $optionElements = $this->getField($optionParameter)->headElements($optionParameter);
94
            $ownElements = array_merge($ownElements, $optionElements);
95
        }
96
97
        return $ownElements;
98
    }
99
100 View Code Duplication
    private function getOptions(Parameter $parameter, $value, $id) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
101
        $options = [];
102
        foreach ($this->getTypes($parameter) as $i => $type) {
103
            $options[] = new Element('option', array_merge([
104
                'value' => "$id-multi-option-$i"
105
            ], $type->is($value) ? [
106
                'selected' => 'selected'
107
            ] : []), [
108
                $this->toString($type)
109
            ]);
110
        }
111
        return $options;
112
    }
113
114
    private function toString(Type $type) {
115
        if ($type instanceof ClassType) {
116
            return (new \ReflectionClass($type->getClass()))->getShortName();
117
        } else {
118
            return (string)$type;
119
        }
120
    }
121
122 View Code Duplication
    private function getTypes(Parameter $parameter) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
123
        $type = $parameter->getType();
124
        if (!($type instanceof MultiType)) {
125
            throw new \InvalidArgumentException("[$type] must be a MultiType");
126
        }
127
128
        return $type->getTypes();
129
    }
130
131
    /**
132
     * @param Parameter $optionParameter
133
     * @return WebField
134
     */
135
    private function getField($optionParameter) {
136
        return $this->fields->getField($optionParameter);
137
    }
138
}