Completed
Pull Request — master (#129)
by
unknown
03:00
created

layoutLine::getId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace eXpansion\Framework\Gui\Layouts;
4
5
use FML\Controls\Control;
6
use FML\Controls\Frame;
7
use FML\Elements\Format;
8
use FML\Script\Features\ScriptFeature;
9
use FML\Types\Container;
10
use FML\Types\Renderable;
11
use FML\Types\ScriptFeatureable;
12
13
class layoutLine implements Renderable, ScriptFeatureable, Container
14
{
15
    protected $frameClasses = [];
16
17
    protected $frameId = null;
18
19
    /** @var float */
20
    protected $width = 0.;
21
22
    /** @var float */
23
    protected $height = 0.;
24
25
    /** @var Control[] */
26
    protected $elements = [];
27
28
    /** @var float */
29
    protected $margin = 2.;
30
    /**
31
     * @var float
32
     */
33
    protected $startX = 0.;
34
    /**
35
     * @var float
36
     */
37
    protected $startY = 0.;
38
39
    /** @var string */
40
    protected $hAlign = "left";
41
42
    /** @var string */
43
    protected $vAlign = "top";
44
45
    /**
46
     * layoutLine constructor.
47
     * @param float $startX
48
     * @param float $startY
49
     * @param object[] $elements
50
     * @param float $margin
51
     * @throws \Exception
52
     */
53
    public function __construct($startX, $startY, $elements = [], $margin = 0.)
54
    {
55
        if (!is_array($elements)) {
56
            throw new \Exception('not an array');
57
        }
58
        $this->margin = $margin;
59
        $this->elements = $elements;
60
        $this->startX = $startX;
61
        $this->startY = $startY;
62
        $sizeY = 0;
63
        foreach ($this->elements as $idx => $element) {
64
            $this->width += $element->getWidth() + $this->margin;
65
            if ($element->getY() + $element->getHeight() > $sizeY) {
66
                $this->setHeight($element->getHeight());
67
            }
68
        }
69
70
    }
71
72
    /**
73
     * Render the XML element
74
     *
75
     * @param \DOMDocument $domDocument DOMDocument for which the XML element should be rendered
76
     * @return \DOMElement
77
     */
78
    public function render(\DOMDocument $domDocument)
79
    {
80
        $frame = new Frame();
81
        $frame->setId($this->frameId);
82
        $frame->setAlign($this->hAlign, $this->vAlign);
83
        $frame->setPosition($this->startX, $this->startY);
84
        $frame->addClasses($this->frameClasses);
85
86
        $startX = 0;
87
        $sizeY = 0;
88
        foreach ($this->elements as $idx => $element) {
89
            $element->setX($startX);
90
            $startX += $element->getWidth() + $this->margin;
91
            if ($element->getY() + $element->getHeight() > $sizeY) {
92
                $this->setHeight($element->getHeight());
93
            }
94
            $frame->addChild($element);
95
        }
96
97
        return $frame->render($domDocument);
98
    }
99
100
    /**
101
     * Get the Script Features
102
     *
103
     * @return ScriptFeature[]
104
     */
105 View Code Duplication
    public function getScriptFeatures()
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...
106
    {
107
        $features = [];
108
        foreach ($this->elements as $element) {
109
            if ($element instanceof ScriptFeatureable) {
110
                $features[] = $element->getScriptFeatures();
111
            }
112
        }
113
114
        return ScriptFeature::collect($features);
115
    }
116
117
    /**
118
     * @param mixed $startX
119
     * @return layoutLine
120
     */
121
    public function setX($startX)
122
    {
123
        $this->startX = $startX;
124
125
        return $this;
126
    }
127
128
    /**
129
     * @param mixed $startY
130
     * @return layoutLine
131
     */
132
    public function setY($startY)
133
    {
134
        $this->startY = $startY;
135
136
        return $this;
137
    }
138
139
    /**
140
     * @return float
141
     */
142
    public function getX()
143
    {
144
        return $this->startX;
145
    }
146
147
    /**
148
     * @return mixed
149
     */
150
    public function getY()
151
    {
152
        return $this->startY;
153
    }
154
155
    /**
156
     * @return float
157
     */
158
    public function getWidth()
159
    {
160
        return $this->width;
161
    }
162
163
    /**
164
     * @param float $width
165
     */
166
    public function setWidth($width)
167
    {
168
        $this->width = $width;
169
    }
170
171
    /**
172
     * @return float
173
     */
174
    public function getHeight()
175
    {
176
        return $this->height;
177
    }
178
179
    /**
180
     * @param float $height
181
     */
182
    public function setHeight($height)
183
    {
184
        $this->height = $height;
185
    }
186
187
    /**
188
     * @param object $element
189
     */
190
    public function addChild(Renderable $element)
191
    {
192
        $this->elements[] = $element;
193
        $this->width += $element->getWidth() + $this->margin;
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface FML\Types\Renderable as the method getWidth() does only exist in the following implementations of said interface: ControlStub, FML\Controls\Audio, FML\Controls\Control, FML\Controls\Entry, FML\Controls\FileEntry, FML\Controls\Frame, FML\Controls\Frame3d, FML\Controls\FrameInstance, FML\Controls\Gauge, FML\Controls\Graph, FML\Controls\Label, FML\Controls\Labels\Label_Button, FML\Controls\Labels\Label_Text, FML\Controls\Quad, FML\Controls\Quads\Quad_321Go, FML\Controls\Quads\Quad_BgRaceScore2, FML\Controls\Quads\Quad_Bgs1, FML\Controls\Quads\Quad_Bgs1InRace, FML\Controls\Quads\Quad_BgsButtons, FML\Controls\Quads\Quad_BgsChallengeMedals, FML\Controls\Quads\Quad_BgsPlayerCard, FML\Controls\Quads\Quad_Copilot, FML\Controls\Quads\Quad_Emblems, FML\Controls\Quads\Quad_EnergyBar, FML\Controls\Quads\Quad_Hud3dEchelons, FML\Controls\Quads\Quad_Hud3dIcons, FML\Controls\Quads\Quad_Icons128x128_1, FML\Controls\Quads\Quad_Icons128x128_Blink, FML\Controls\Quads\Quad_Icons128x32_1, FML\Controls\Quads\Quad_Icons64x64_1, FML\Controls\Quads\Quad_Icons64x64_2, FML\Controls\Quads\Quad_ManiaPlanetLogos, FML\Controls\Quads\Quad_ManiaPlanetMainMenu, FML\Controls\Quads\Quad_ManiaplanetSystem, FML\Controls\Quads\Quad_MedalsBig, FML\Controls\Quads\Quad_TitleLogos, FML\Controls\Quads\Quad_...structionBullet_Buttons, FML\Controls\Quads\Quad_UIConstruction_Buttons, FML\Controls\Quads\Quad_UIConstruction_Buttons2, FML\Controls\Quads\Quad_UiSMSpectatorScoreBig, FML\Controls\TextEdit, FML\Controls\Video, eXpansion\Framework\Gui\...nents\abstractUiElement, eXpansion\Framework\Gui\Components\uiAnimation, eXpansion\Framework\Gui\Components\uiButton, eXpansion\Framework\Gui\Components\uiCheckbox, eXpansion\Framework\Gui\Components\uiDropdown, eXpansion\Framework\Gui\Components\uiInput, eXpansion\Framework\Gui\Components\uiInputMasked, eXpansion\Framework\Gui\Components\uiLabel, eXpansion\Framework\Gui\Components\uiLine, eXpansion\Framework\Gui\Components\uiScrollbar, eXpansion\Framework\Gui\Components\uiTextbox, eXpansion\Framework\Gui\Components\uiTooltip, eXpansion\Framework\Gui\Layouts\layoutLine, eXpansion\Framework\Gui\Layouts\layoutRow, eXpansion\Framework\Gui\Layouts\layoutScrollable.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
194
        $this->height += $element->getHeight();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface FML\Types\Renderable as the method getHeight() does only exist in the following implementations of said interface: ControlStub, FML\Controls\Audio, FML\Controls\Control, FML\Controls\Entry, FML\Controls\FileEntry, FML\Controls\Frame, FML\Controls\Frame3d, FML\Controls\FrameInstance, FML\Controls\Gauge, FML\Controls\Graph, FML\Controls\Label, FML\Controls\Labels\Label_Button, FML\Controls\Labels\Label_Text, FML\Controls\Quad, FML\Controls\Quads\Quad_321Go, FML\Controls\Quads\Quad_BgRaceScore2, FML\Controls\Quads\Quad_Bgs1, FML\Controls\Quads\Quad_Bgs1InRace, FML\Controls\Quads\Quad_BgsButtons, FML\Controls\Quads\Quad_BgsChallengeMedals, FML\Controls\Quads\Quad_BgsPlayerCard, FML\Controls\Quads\Quad_Copilot, FML\Controls\Quads\Quad_Emblems, FML\Controls\Quads\Quad_EnergyBar, FML\Controls\Quads\Quad_Hud3dEchelons, FML\Controls\Quads\Quad_Hud3dIcons, FML\Controls\Quads\Quad_Icons128x128_1, FML\Controls\Quads\Quad_Icons128x128_Blink, FML\Controls\Quads\Quad_Icons128x32_1, FML\Controls\Quads\Quad_Icons64x64_1, FML\Controls\Quads\Quad_Icons64x64_2, FML\Controls\Quads\Quad_ManiaPlanetLogos, FML\Controls\Quads\Quad_ManiaPlanetMainMenu, FML\Controls\Quads\Quad_ManiaplanetSystem, FML\Controls\Quads\Quad_MedalsBig, FML\Controls\Quads\Quad_TitleLogos, FML\Controls\Quads\Quad_...structionBullet_Buttons, FML\Controls\Quads\Quad_UIConstruction_Buttons, FML\Controls\Quads\Quad_UIConstruction_Buttons2, FML\Controls\Quads\Quad_UiSMSpectatorScoreBig, FML\Controls\TextEdit, FML\Controls\Video, eXpansion\Framework\Gui\...nents\abstractUiElement, eXpansion\Framework\Gui\Components\uiAnimation, eXpansion\Framework\Gui\Components\uiButton, eXpansion\Framework\Gui\Components\uiCheckbox, eXpansion\Framework\Gui\Components\uiDropdown, eXpansion\Framework\Gui\Components\uiInput, eXpansion\Framework\Gui\Components\uiInputMasked, eXpansion\Framework\Gui\Components\uiLabel, eXpansion\Framework\Gui\Components\uiLine, eXpansion\Framework\Gui\Components\uiScrollbar, eXpansion\Framework\Gui\Components\uiTextbox, eXpansion\Framework\Gui\Components\uiTooltip, eXpansion\Framework\Gui\Layouts\layoutLine, eXpansion\Framework\Gui\Layouts\layoutRow, eXpansion\Framework\Gui\Layouts\layoutScrollable.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
195
    }
196
197
    public function getChildren()
198
    {
199
        return $this->elements;
200
    }
201
202
203
    public function addClass($class)
204
    {
205
        $this->frameClasses [] = $class;
206
    }
207
208
    /**
209
     * Add a new child
210
     *
211
     * @api
212
     * @param Renderable $child Child Control to add
213
     * @return static
214
     * @deprecated Use addChild()
215
     * @see        Container::addChild()
216
     */
217
    public function add(Renderable $child)
218
    {
219
        // TODO: Implement add() method.
220
    }
221
222
    /**
223
     * Add new children
224
     *
225
     * @api
226
     * @param Renderable[] $children Child Controls to add
227
     * @return static
228
     */
229
    public function addChildren(array $children)
230
    {
231
        foreach ($children as $child) {
232
            $this->addChild($child);
233
        }
234
    }
235
236
    /**
237
     * Remove all children
238
     *
239
     * @api
240
     * @return static
241
     */
242
    public function removeAllChildren()
243
    {
244
        $this->width = 0;
0 ignored issues
show
Documentation Bug introduced by
The property $width was declared of type double, but 0 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
245
        $this->height = 0;
0 ignored issues
show
Documentation Bug introduced by
The property $height was declared of type double, but 0 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
246
        $this->elements = [];
247
248
        return $this;
249
    }
250
251
    /**
252
     * Remove all children
253
     *
254
     * @api
255
     * @return static
256
     * @deprecated Use removeAllChildren()
257
     * @see        Container::removeAllChildren()
258
     */
259
    public function removeChildren()
260
    {
261
        // TODO: Implement removeChildren() method.
262
    }
263
264
    /**
265
     * Get the Format
266
     *
267
     * @api
268
     * @param bool $createIfEmpty If the format should be created if it doesn't exist yet
269
     * @return Format
270
     * @deprecated Use Style
271
     * @see        Style
272
     */
273
    public function getFormat($createIfEmpty = true)
274
    {
275
        // TODO: Implement getFormat() method.
276
    }
277
278
    /**
279
     * Set the Format
280
     *
281
     * @api
282
     * @param Format $format New Format
283
     * @return static
284
     * @deprecated Use Style
285
     * @see        Style
286
     */
287
    public function setFormat(Format $format = null)
288
    {
289
        // TODO: Implement setFormat() method.
290
    }
291
292
    public function setAlign($hAling = "left", $vAlign = "top")
293
    {
294
        $this->halign = $hAling;
0 ignored issues
show
Bug introduced by
The property halign does not seem to exist. Did you mean hAlign?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
295
        $this->valign = $vAlign;
0 ignored issues
show
Bug introduced by
The property valign does not seem to exist. Did you mean vAlign?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
296
    }
297
298
299
    public function setPosition($x, $y)
300
    {
301
        $this->setX($x);
302
        $this->setY($y);
303
304
        return $this;
305
    }
306
307
    /**
308
     * @return null|string
309
     */
310
    public function getId()
311
    {
312
        return $this->frameId;
313
    }
314
315
    /**
316
     * @param null|string $frameId
317
     */
318
    public function setId($frameId)
319
    {
320
        $this->frameId = $frameId;
321
    }
322
323
}
324