Completed
Push — master ( f5ebce...5cc08a )
by Jan
04:25
created

AmountFormatter::format()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 27
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 13
nc 5
nop 3
dl 0
loc 27
rs 9.8333
c 1
b 0
f 0
1
<?php
2
/**
3
 *
4
 * part-db version 0.1
5
 * Copyright (C) 2005 Christoph Lechner
6
 * http://www.cl-projects.de/
7
 *
8
 * part-db version 0.2+
9
 * Copyright (C) 2009 K. Jacobs and others (see authors.php)
10
 * http://code.google.com/p/part-db/
11
 *
12
 * Part-DB Version 0.4+
13
 * Copyright (C) 2016 - 2019 Jan Böhmer
14
 * https://github.com/jbtronics
15
 *
16
 * This program is free software; you can redistribute it and/or
17
 * modify it under the terms of the GNU General Public License
18
 * as published by the Free Software Foundation; either version 2
19
 * of the License, or (at your option) any later version.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 * GNU General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU General Public License
27
 * along with this program; if not, write to the Free Software
28
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
29
 *
30
 */
31
32
namespace App\Services;
33
34
35
use App\Entity\Parts\MeasurementUnit;
36
use Symfony\Component\OptionsResolver\Options;
37
use Symfony\Component\OptionsResolver\OptionsResolver;
38
39
/**
40
 * This service formats an part amout using a Measurement Unit.
41
 * @package App\Services
42
 */
43
class AmountFormatter
44
{
45
    protected $siFormatter;
46
47
    public function __construct(SIFormatter $siFormatter)
48
    {
49
        $this->siFormatter = $siFormatter;
50
    }
51
52
    protected function configureOptions(OptionsResolver $resolver)
53
    {
54
        $resolver->setDefaults([
55
            'show_prefix' => function (Options $options) {
56
                if ($options['measurement_unit'] !== null) {
57
                    /** @var MeasurementUnit $unit */
58
                    $unit = $options['measurement_unit'];
59
                    return $unit->isUseSIPrefix();
60
                }
61
                return true;
62
            },
63
            'is_integer' => function (Options $options) {
64
                if ($options['measurement_unit'] !== null) {
65
                    /** @var MeasurementUnit $unit */
66
                    $unit = $options['measurement_unit'];
67
                    return $unit->isInteger();
68
                }
69
                return true;
70
            },
71
            'unit' => function (Options $options) {
72
                if ($options['measurement_unit'] !== null) {
73
                    /** @var MeasurementUnit $unit */
74
                    $unit = $options['measurement_unit'];
75
                    return $unit->getUnit();
76
                }
77
                return '';
78
            },
79
            'decimals' => 2,
80
            'error_mapping' => [ '.' => 'value']
81
        ]);
82
83
        $resolver->setAllowedTypes('decimals', 'int');
84
85
        $resolver->setNormalizer('decimals', function (Options $options, $value) {
86
            // If the unit is integer based, then dont show any decimals
87
            if ($options['is_integer']) {
88
                return 0;
89
            }
90
            return $value;
91
        });
92
    }
93
94
    /**
95
     * Formats the given value using the measurement unit and options.
96
     * @param $value float|int The value that should be formatted. Must be numeric.
97
     * @param MeasurementUnit|null $unit The measurement unit, whose unit symbol should be used for formatting.
98
     *              If set to null, it is assumed that the part amount is measured in pieces.
99
     * @param array $options
100
     * @return string The formatted string
101
     * @throws \InvalidArgumentException Thrown if $value is not numeric.
102
     */
103
    public function format($value, ?MeasurementUnit $unit = null, array $options = [])
104
    {
105
        if (!is_numeric($value)) {
106
            throw new \InvalidArgumentException('$value must be an numeric value!');
107
        }
108
109
        $value = (float) $value;
110
111
        //Find out what options to use
112
        $resolver = new OptionsResolver();
113
        $resolver->setDefault('measurement_unit', $unit);
114
        $this->configureOptions($resolver);
115
116
        $options = $resolver->resolve($options);
117
118
        if ($options['is_integer']) {
119
            $value = round($value);
120
        }
121
122
        //If the measurement unit uses a SI prefix format it that way.
123
        if ($options['show_prefix']) {
124
            return $this->siFormatter->format($value, $options['unit'], $options['decimals']);
125
        }
126
127
        //Otherwise just output it
128
        $format_string = '%.' . $options['decimals'] . 'f ' . $options['unit'];
129
        return sprintf($format_string, $value);
130
    }
131
}