Completed
Pull Request — master (#263)
by AntikCz
10:32
created

Container::addExport()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 10
ccs 7
cts 7
cp 1
rs 9.4285
cc 2
eloc 7
nc 2
nop 2
crap 2
1
<?php
2
3
/**
4
 * This file is part of the Grido (http://grido.bugyik.cz)
5
 *
6
 * Copyright (c) 2011 Petr Bugyík (http://petr.bugyik.cz)
7
 *
8
 * For the full copyright and license information, please view
9
 * the file license.md that was distributed with this source code.
10
 */
11
12
namespace Grido\Components;
13
14
use Grido\Components\Exports\BaseExport;
15
use Grido\Components\Exports\CsvExport;
16
use Grido\Grid;
17
use Grido\Helpers;
18
use Grido\Components\Actions\Action;
19
use Grido\Components\Columns\Column;
20
use Grido\Components\Filters\Filter;
21
use Grido\Components\Columns\Editable;
22
23
/**
24
 * Container of grid components.
25
 *
26
 * @package     Grido
27
 * @subpackage  Components
28
 * @author      Petr Bugyík
29
 *
30
 */
31
abstract class Container extends \Nette\Application\UI\Control
32 1
{
33
    /** @var bool */
34
    protected $hasColumns;
35
36
    /** @var bool */
37
    protected $hasFilters;
38
39
    /** @var bool */
40
    protected $hasActions;
41
42
    /** @var bool */
43
    protected $hasOperation;
44
45
    /** @var bool */
46
    protected $hasExport;
47
48 1
    /**
49
     * Returns column component.
50
     * @param string $name
51 1
     * @param bool $need
52
     * @return Editable
53
     */
54
    public function getColumn($name, $need = TRUE)
55
    {
56 1
        return $this->hasColumns()
57 1
            ? $this->getComponent(Column::ID)->getComponent(Helpers::formatColumnName($name), $need)
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Nette\ComponentModel\IComponent as the method getComponent() does only exist in the following implementations of said interface: Grido\Components\Actions\Action, Grido\Components\Actions\Event, Grido\Components\Actions\Href, Grido\Components\Columns\Column, Grido\Components\Columns\Date, Grido\Components\Columns\Editable, Grido\Components\Columns\Email, Grido\Components\Columns\Link, Grido\Components\Columns\Number, Grido\Components\Columns\Text, Grido\Components\Component, Grido\Components\Container, Grido\Components\Exports\BaseExport, Grido\Components\Exports\CsvExport, Grido\Components\Filters\Check, Grido\Components\Filters\Custom, Grido\Components\Filters\Date, Grido\Components\Filters\DateRange, Grido\Components\Filters\Filter, Grido\Components\Filters\Number, Grido\Components\Filters\Select, Grido\Components\Filters\Text, Grido\Components\Operation, Grido\Grid, KdybyModule\CliPresenter, Nette\Application\UI\Control, Nette\Application\UI\Form, Nette\Application\UI\Multiplier, Nette\Application\UI\Presenter, Nette\Application\UI\PresenterComponent, Nette\ComponentModel\Container, Nette\Forms\Container, Nette\Forms\Form.

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...
58 1
            : NULL;
59
    }
60
61
    /**
62
     * Returns filter component.
63
     * @param string $name
64
     * @param bool $need
65
     * @return Filter
66
     */
67
    public function getFilter($name, $need = TRUE)
68
    {
69 1
        return $this->hasFilters()
70 1
            ? $this->getComponent(Filter::ID)->getComponent(Helpers::formatColumnName($name), $need)
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Nette\ComponentModel\IComponent as the method getComponent() does only exist in the following implementations of said interface: Grido\Components\Actions\Action, Grido\Components\Actions\Event, Grido\Components\Actions\Href, Grido\Components\Columns\Column, Grido\Components\Columns\Date, Grido\Components\Columns\Editable, Grido\Components\Columns\Email, Grido\Components\Columns\Link, Grido\Components\Columns\Number, Grido\Components\Columns\Text, Grido\Components\Component, Grido\Components\Container, Grido\Components\Exports\BaseExport, Grido\Components\Exports\CsvExport, Grido\Components\Filters\Check, Grido\Components\Filters\Custom, Grido\Components\Filters\Date, Grido\Components\Filters\DateRange, Grido\Components\Filters\Filter, Grido\Components\Filters\Number, Grido\Components\Filters\Select, Grido\Components\Filters\Text, Grido\Components\Operation, Grido\Grid, KdybyModule\CliPresenter, Nette\Application\UI\Control, Nette\Application\UI\Form, Nette\Application\UI\Multiplier, Nette\Application\UI\Presenter, Nette\Application\UI\PresenterComponent, Nette\ComponentModel\Container, Nette\Forms\Container, Nette\Forms\Form.

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...
71 1
            : NULL;
72
    }
73
74
    /**
75
     * Returns action component.
76
     * @param string $name
77
     * @param bool $need
78
     * @return Action
79
     */
80
    public function getAction($name, $need = TRUE)
81
    {
82 1
        return $this->hasActions()
83 1
            ? $this->getComponent(Action::ID)->getComponent($name, $need)
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Nette\ComponentModel\IComponent as the method getComponent() does only exist in the following implementations of said interface: Grido\Components\Actions\Action, Grido\Components\Actions\Event, Grido\Components\Actions\Href, Grido\Components\Columns\Column, Grido\Components\Columns\Date, Grido\Components\Columns\Editable, Grido\Components\Columns\Email, Grido\Components\Columns\Link, Grido\Components\Columns\Number, Grido\Components\Columns\Text, Grido\Components\Component, Grido\Components\Container, Grido\Components\Exports\BaseExport, Grido\Components\Exports\CsvExport, Grido\Components\Filters\Check, Grido\Components\Filters\Custom, Grido\Components\Filters\Date, Grido\Components\Filters\DateRange, Grido\Components\Filters\Filter, Grido\Components\Filters\Number, Grido\Components\Filters\Select, Grido\Components\Filters\Text, Grido\Components\Operation, Grido\Grid, KdybyModule\CliPresenter, Nette\Application\UI\Control, Nette\Application\UI\Form, Nette\Application\UI\Multiplier, Nette\Application\UI\Presenter, Nette\Application\UI\PresenterComponent, Nette\ComponentModel\Container, Nette\Forms\Container, Nette\Forms\Form.

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...
84 1
            : NULL;
85
    }
86
87
    /**
88
     * Returns operations component.
89
     * @param bool $need
90
     * @return Operation
91
     */
92
    public function getOperation($need = TRUE)
93
    {
94 1
        return $this->getComponent(Operation::ID, $need);
95
    }
96
97
    /**
98
     * Returns export component.
99
     * @param bool $need
100
     * @return CsvExport
101
     *
102
     * @deprecated
103
     */
104
    public function getExport($need = TRUE)
105
    {
106 1
        $export = $this->getComponent(BaseExport::ID, $need);
107 1
        if ($export) {
108 1
            $export = $export->getComponent(CsvExport::CSV_ID, $need);
0 ignored issues
show
Deprecated Code introduced by
The constant Grido\Components\Exports\CsvExport::CSV_ID has been deprecated.

This class constant has been deprecated.

Loading history...
109 1
        }
110 1
        return $export;
111
    }
112
113
    /**
114
     * @param bool $need
115
     * @return BaseExport[]
116
     */
117
    public function getExports($need = TRUE)
118
    {
119 1
        $export = $this->getComponent(BaseExport::ID, $need);
120 1
        if ($export) {
121 1
            $export = $export->getComponents();
122 1
        }
123 1
        return $export;
124
    }
125
126
    /**********************************************************************************************/
127
128
    /**
129
     * @param bool $useCache
130
     * @return bool
131
     * @internal
132
     */
133
    public function hasColumns($useCache = TRUE)
134
    {
135 1
        $hasColumns = $this->hasColumns;
136
137 1
        if ($hasColumns === NULL || $useCache === FALSE) {
138 1
            $container = $this->getComponent(Column::ID, FALSE);
139 1
            $hasColumns = $container && count($container->getComponents()) > 0;
140 1
            $this->hasColumns = $useCache ? $hasColumns : NULL;
141 1
        }
142
143 1
        return $hasColumns;
144
    }
145
146
    /**
147
     * @param bool $useCache
148
     * @return bool
149
     * @internal
150
     */
151
    public function hasFilters($useCache = TRUE)
152
    {
153 1
        $hasFilters = $this->hasFilters;
154
155 1
        if ($hasFilters === NULL || $useCache === FALSE) {
156 1
            $container = $this->getComponent(Filter::ID, FALSE);
157 1
            $hasFilters = $container && count($container->getComponents()) > 0;
158 1
            $this->hasFilters = $useCache ? $hasFilters : NULL;
159 1
        }
160
161 1
        return $hasFilters;
162
    }
163
164
    /**
165
     * @param bool $useCache
166 1
     * @return bool
167
     * @internal
168
     */
169
    public function hasActions($useCache = TRUE)
170
    {
171 1
        $hasActions = $this->hasActions;
172
173 1
        if ($hasActions === NULL || $useCache === FALSE) {
174 1
            $container = $this->getComponent(Action::ID, FALSE);
175 1
            $hasActions = $container && count($container->getComponents()) > 0;
176 1
            $this->hasActions = $useCache ? $hasActions : NULL;
177 1
        }
178
179 1
        return $hasActions;
180
    }
181
182
    /**
183
     * @param bool $useCache
184
     * @return bool
185
     * @internal
186
     */
187
    public function hasOperation($useCache = TRUE)
188
    {
189 1
        $hasOperation = $this->hasOperation;
190
191 1
        if ($hasOperation === NULL || $useCache === FALSE) {
192 1
            $hasOperation = (bool) $this->getComponent(Operation::ID, FALSE);
193 1
            $this->hasOperation = $useCache ? $hasOperation : NULL;
194 1
        }
195
196 1
        return $hasOperation;
197
    }
198
199
    /**
200
     * @param bool $useCache
201
     * @return bool
202
     * @internal
203
     */
204
    public function hasExport($useCache = TRUE)
205
    {
206 1
        $hasExport = $this->hasExport;
207
208 1
        if ($hasExport === NULL || $useCache === FALSE) {
209 1
            $hasExport = (bool) $this->getExports(FALSE);
210 1
            $this->hasExport = $useCache ? $hasExport : NULL;
211 1
        }
212
213 1
        return $hasExport;
214
    }
215
216
    /**********************************************************************************************/
217
218
    /**
219
     * @param string $name
220
     * @param string $label
221
     * @return Columns\Text
222
     */
223
    public function addColumnText($name, $label)
224
    {
225 1
        return new Columns\Text($this, $name, $label);
226
    }
227
228
    /**
229
     * @param string $name
230
     * @param string $label
231
     * @return Columns\Email
232
     */
233
    public function addColumnEmail($name, $label)
234
    {
235 1
        return new Columns\Email($this, $name, $label);
236
    }
237
238
    /**
239
     * @param string $name
240
     * @param string $label
241
     * @return Columns\Link
242
     */
243
    public function addColumnLink($name, $label)
244
    {
245 1
        return new Columns\Link($this, $name, $label);
246
    }
247
248
    /**
249
     * @param string $name
250
     * @param string $label
251
     * @param string $dateFormat
252
     * @return Columns\Date
253
     */
254
    public function addColumnDate($name, $label, $dateFormat = NULL)
255
    {
256 1
        return new Columns\Date($this, $name, $label, $dateFormat);
257
    }
258
259
    /**
260
     * @param string $name
261
     * @param string $label
262
     * @param int $decimals number of decimal points
263
     * @param string $decPoint separator for the decimal point
264
     * @param string $thousandsSep thousands separator
265
     * @return Columns\Number
266
     */
267
    public function addColumnNumber($name, $label, $decimals = NULL, $decPoint = NULL, $thousandsSep = NULL)
268
    {
269 1
        return new Columns\Number($this, $name, $label, $decimals, $decPoint, $thousandsSep);
270
    }
271
272
    /**********************************************************************************************/
273
274
    /**
275
     * @param string $name
276
     * @param string $label
277
     * @return Filters\Text
278
     */
279
    public function addFilterText($name, $label)
280
    {
281 1
        return new Filters\Text($this, $name, $label);
282
    }
283
284
    /**
285
     * @param string $name
286
     * @param string $label
287
     * @return Filters\Date
288
     */
289
    public function addFilterDate($name, $label)
290
    {
291 1
        return new Filters\Date($this, $name, $label);
292
    }
293
294
    /**
295
     * @param string $name
296
     * @param string $label
297
     * @return Filters\DateRange
298
     */
299
    public function addFilterDateRange($name, $label)
300
    {
301 1
        return new Filters\DateRange($this, $name, $label);
302
    }
303
304
    /**
305
     * @param string $name
306
     * @param string $label
307
     * @return Filters\Check
308
     */
309
    public function addFilterCheck($name, $label)
310
    {
311 1
        return new Filters\Check($this, $name, $label);
312
    }
313
314
    /**
315
     * @param string $name
316
     * @param string $label
317
     * @param array $items
318
     * @return Filters\Select
319
     */
320
    public function addFilterSelect($name, $label, array $items = NULL)
321
    {
322 1
        return new Filters\Select($this, $name, $label, $items);
323
    }
324
325
    /**
326
     * @param string $name
327
     * @param string $label
328
     * @return Filters\Number
329
     */
330
    public function addFilterNumber($name, $label)
331
    {
332 1
        return new Filters\Number($this, $name, $label);
333
    }
334
335
    /**
336
     * @param string $name
337
     * @param \Nette\Forms\IControl $formControl
338
     * @return Filters\Custom
339
     */
340
    public function addFilterCustom($name, \Nette\Forms\IControl $formControl)
341
    {
342 1
        return new Filters\Custom($this, $name, NULL, $formControl);
343
    }
344
345
    /**********************************************************************************************/
346
347
    /**
348
     * @param string $name
349
     * @param string $label
350
     * @param string $destination
351
     * @param array $arguments
352
     * @return Actions\Href
353
     */
354
    public function addActionHref($name, $label, $destination = NULL, array $arguments = [])
355
    {
356 1
        return new Actions\Href($this, $name, $label, $destination, $arguments);
357
    }
358
359
    /**
360
     * @param string $name
361
     * @param string $label
362
     * @param callback $onClick
363
     * @return Actions\Event
364
     */
365
    public function addActionEvent($name, $label, $onClick = NULL)
366
    {
367 1
        return new Actions\Event($this, $name, $label, $onClick);
368
    }
369
370
    /**********************************************************************************************/
371
372
    /**
373
     * @param array $operations
374
     * @param callback $onSubmit - callback after operation submit
375
     * @return Operation
376
     */
377
    public function setOperation(array $operations, $onSubmit)
378
    {
379 1
        return new Operation($this, $operations, $onSubmit);
380
    }
381
382
    /**
383
     * @param string $label of exporting file
384
     * @return Export
385
     *
386
     * @deprecated
387
     */
388
    public function setExport($label = NULL)
389
    {
390 1
        return $this->addExport(new CsvExport($label), CsvExport::CSV_ID);
0 ignored issues
show
Deprecated Code introduced by
The constant Grido\Components\Exports\CsvExport::CSV_ID has been deprecated.

This class constant has been deprecated.

Loading history...
391
    }
392
393
    /**
394
     * @param BaseExport $export
395
     * @param string $name Component name
396
     * @return BaseExport
397
     */
398
    public function addExport(BaseExport $export, $name)
399
    {
400 1
        $container = $this->getComponent(BaseExport::ID, FALSE);
401 1
        if (!$container) {
402 1
            $container = new \Nette\ComponentModel\Container();
403 1
            $this->addComponent($container, BaseExport::ID);
404 1
        }
405 1
        $container->addComponent($export, $name);
406 1
        return $export;
407
    }
408
409
    /**
410
     * Sets all columns as editable.
411
     * First parameter is optional and is for implementation of method for saving modified data.
412
     * @param callback $callback function($id, $newValue, $oldValue, Editable $column) {}
413
     * @return Grid
414
     */
415
    public function setEditableColumns($callback = NULL)
416
    {
417 1
        $this->onRender[] = function(Grid $grid) use ($callback) {
0 ignored issues
show
Documentation introduced by
The property onRender does not exist on object<Grido\Components\Container>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
418 1
            if (!$grid->hasColumns()) {
419
                return;
420
            }
421
422 1
            foreach ($grid->getComponent(Column::ID)->getComponents() as $column) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Nette\ComponentModel\IComponent as the method getComponents() does only exist in the following implementations of said interface: Grido\Components\Actions\Action, Grido\Components\Actions\Event, Grido\Components\Actions\Href, Grido\Components\Columns\Column, Grido\Components\Columns\Date, Grido\Components\Columns\Editable, Grido\Components\Columns\Email, Grido\Components\Columns\Link, Grido\Components\Columns\Number, Grido\Components\Columns\Text, Grido\Components\Component, Grido\Components\Container, Grido\Components\Exports\BaseExport, Grido\Components\Exports\CsvExport, Grido\Components\Filters\Check, Grido\Components\Filters\Custom, Grido\Components\Filters\Date, Grido\Components\Filters\DateRange, Grido\Components\Filters\Filter, Grido\Components\Filters\Number, Grido\Components\Filters\Select, Grido\Components\Filters\Text, Grido\Components\Operation, Grido\Grid, KdybyModule\CliPresenter, Nette\Application\UI\Control, Nette\Application\UI\Form, Nette\Application\UI\Multiplier, Nette\Application\UI\Presenter, Nette\Application\UI\PresenterComponent, Nette\ComponentModel\Container, Nette\Forms\Container, Nette\Forms\Form.

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...
423 1
                if ($column instanceof Editable && !$column->isEditableDisabled() && !$column->editableCallback) {
424 1
                    $column->setEditable($callback);
425 1
                }
426 1
            }
427 1
        };
428
429 1
        return $this;
430
    }
431
}
432