Completed
Push — master ( 1e7f46...dd3edb )
by Carsten
04:51 queued 02:32
created

DevelopingFactory::extractDensities()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
namespace FilmTools\Developing;
3
4
use FilmTools\Commons\Zones;
5
use FilmTools\Commons\FStops;
6
use FilmTools\Commons\Exposures;
7
use FilmTools\Commons\ExposuresProviderInterface;
8
use FilmTools\Commons\Densities;
9
use FilmTools\Commons\DensitiesProviderInterface;
10
11
class DevelopingFactory
12
{
13
14
    /**
15
     * PHP class name (FQDN) of the DevelopingInterface instance this factory produces.
16
     *
17
     * @var string
18
     */
19
    public $developing_php_class;
20
21
22
    /**
23
     * @param string|null $developing_php_class DevelopingInterface instance FQDN
24
     *
25
     * @throws InvalidArgumentException If FQDN does not implement DevelopingInterface
26
     */
27 36
    public function __construct( string $developing_php_class = null )
28
    {
29 36
        $this->developing_php_class = $developing_php_class ?: Developing::class;
30
31 36
        if (!is_subclass_of($this->developing_php_class, DevelopingInterface::class )):
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \FilmTools\Developing\DevelopingInterface::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
32 3
            $msg = sprintf("Class name must implement '%s'.", DevelopingInterface::class);
33 3
            throw new DevelopingInvalidArgumentException( $msg );
34
        endif;
35 33
    }
36
37
38
    /**
39
     * The factory method.
40
     *
41
     * Expects an array or ArrayAccess with at least elements "time", "densities", and "exposures".
42
     *
43
     * If no "exposures" are given, but "zones" numbers are instead, the zone numbers
44
     * will be converted internally.
45
     *
46
     * @param  array|ArrayAccess $developing
47
     * @return DevelopingInterface
48
     */
49 33
    public function __invoke( $developing ) : DevelopingInterface
50
    {
51 33
        if (!is_array($developing) and !$developing instanceOf \ArrayAccess)
52 3
            throw new DevelopingInvalidArgumentException("Array or ArrayAccess expected");
53
54 30
        $densities = $this->extractDensities($developing);
55 30
        $exposures = $this->extractExposures($developing);
56 30
        $time      = $this->extractTime($developing);
57
58 12
        $developing_php_class = $this->developing_php_class;
59 12
        return new $developing_php_class( $exposures, $densities, $time );
60
    }
61
62
63 30
    protected function extractDensities( $developing ) : DensitiesProviderInterface
64
    {
65 30
        $densities = $developing['densities'] ?? array();
66
67 30
        return new Densities($densities);
68
    }
69
70
71 30
    protected function extractExposures( $developing ) : ExposuresProviderInterface
72
    {
73 30
        $fstops    = $developing['fstops']    ?? array();
74 30
        $zones     = $developing['zones']     ?? array();
75 30
        $exposures = $developing['exposures'] ?? array();
76
77
78 30
        if (empty($exposures) and !empty($zones)):
79 21
            $exposures = new Zones( $zones );
80 9
        elseif (empty($exposures) and !empty($fstops)):
81 3
            $exposures = new FStops( $fstops );
82
        else:
83 6
            $exposures = new Exposures( $exposures );
84
        endif;
85
86 30
        return $exposures;
87
    }
88
89
90 30
    protected function extractTime( $developing ) : int
91
    {
92 30
        if (!array_key_exists("time", $developing)
93 30
        and !array_key_exists("seconds", $developing))
94 3
            throw new NoTimeGivenException("The data array must contain either 'time' or 'seconds' element.");
95
96 27
        $time = $developing['seconds'] ?? ($developing['time'] ?? false);
97
98
        // Remove surfluous time values
99 27
        if (is_array($time)):
100 6
            $time = array_unique($time);
101 6
            $count_times = count($time);
102 6
            if ($count_times > 1):
103 3
                $msg = sprintf("There must only be one developing time, %s given", $count_times);
104 3
                throw new NoTimeGivenException($msg);
105
            endif;
106 3
            $time = array_shift($time);
107
        endif;
108
109 24
        if (filter_var($time, \FILTER_VALIDATE_INT, ['options' => array( 'min_range' => 0 )]) === false)
110 12
            throw new NoTimeGivenException("The developing time must be integer (positive or 0).");
111
112 12
        return $time;
113
    }
114
}
115