Conversion   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 128
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 128
rs 10
c 0
b 0
f 0
wmc 15

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 2
A run() 0 7 2
A applyProcessors() 0 17 4
A addListener() 0 7 2
A notifyListeners() 0 12 2
A addProcessor() 0 11 3
1
<?php
2
3
namespace AmaTeam\Image\Projection\Framework;
4
5
use AmaTeam\Image\Projection\API\ConversionInterface;
6
use AmaTeam\Image\Projection\API\Conversion\ListenerInterface;
7
use AmaTeam\Image\Projection\API\Conversion\ProcessorInterface;
8
use AmaTeam\Image\Projection\API\SpecificationInterface;
9
use AmaTeam\Image\Projection\API\Tile\TileInterface;
10
use AmaTeam\Image\Projection\API\Type\GeneratorInterface;
11
use Psr\Log\LoggerAwareInterface;
12
use Psr\Log\LoggerInterface;
13
use Psr\Log\NullLogger;
14
15
/**
16
 * Single-run conversion processing that encapsulates all userspace handlers.
17
 */
18
class Conversion implements ConversionInterface
19
{
20
    /**
21
     * @var SpecificationInterface
22
     */
23
    private $target;
24
    /**
25
     * @var GeneratorInterface
26
     */
27
    private $generator;
28
    /**
29
     * @var ListenerInterface[]
30
     */
31
    private $listeners = [];
32
    /**
33
     * @var ProcessorInterface[][]
34
     */
35
    private $processors = [];
36
    /**
37
     * @var LoggerInterface
38
     */
39
    private $logger;
40
41
    /**
42
     * @param SpecificationInterface $target
43
     * @param GeneratorInterface $generator
44
     * @param LoggerInterface|null $logger
45
     */
46
    public function __construct(
47
        SpecificationInterface $target,
48
        GeneratorInterface $generator,
49
        LoggerInterface $logger = null
50
    ) {
51
        $this->target = $target;
52
        $this->generator = $generator;
53
        $this->logger = $logger ?: new NullLogger();
54
    }
55
56
    /**
57
     * Runs whole pipeline. Tiles are destroyed after last listener has been
58
     * called.
59
     */
60
    public function run()
61
    {
62
        foreach ($this->generator as $tile) {
63
            $context = ['tile' => $tile->getPosition()];
64
            $this->logger->debug('Generated tile {tile}', $context);
65
            $tile = $this->applyProcessors($tile, $this->target);
66
            $this->notifyListeners($tile, $this->target);
67
        }
68
    }
69
70
    /**
71
     * @param TileInterface $tile
72
     * @param SpecificationInterface $specification
73
     * @return TileInterface
74
     */
75
    private function applyProcessors(
76
        TileInterface $tile,
77
        SpecificationInterface $specification
78
    ) {
79
        foreach ($this->processors as $processors) {
80
            foreach ($processors as $processor) {
81
                $context = [
82
                    'tile' => $tile->getPosition(),
83
                    'processor' => $processor
84
                ];
85
                $template = 'Applying processor {processor} to tile {tile}';
86
                $this->logger->debug($template, $context);
87
                $candidate = $processor->process($tile, $specification);
88
                $tile = $candidate instanceof TileInterface ? $candidate : $tile;
89
            }
90
        }
91
        return $tile;
92
    }
93
94
    /**
95
     * @param TileInterface $tile
96
     * @param SpecificationInterface $specification
97
     */
98
    private function notifyListeners(
99
        TileInterface $tile,
100
        SpecificationInterface $specification
101
    ) {
102
        foreach ($this->listeners as $listener) {
103
            $context = [
104
                'tile' => $tile->getPosition(),
105
                'listener' => $listener
106
            ];
107
            $template = 'Applying listener {listener} to tile {tile}';
108
            $this->logger->debug($template, $context);
109
            $listener->accept($tile, $specification);
110
        }
111
    }
112
113
    /**
114
     * @param ProcessorInterface $processor
115
     * @param int $order Order in which processors are applied (lower order.
116
     * values force processors to be run earlier). Processor with same order
117
     * value will be run in the order they were added.
118
     * priority
119
     *
120
     * @return $this
121
     */
122
    public function addProcessor(ProcessorInterface $processor, $order = 0)
123
    {
124
        if ($processor instanceof LoggerAwareInterface) {
125
            $processor->setLogger($this->logger);
126
        }
127
        if (!isset($this->processors[$order])) {
128
            $this->processors[$order] = [];
129
        }
130
        $this->processors[$order][] = $processor;
131
        ksort($this->processors);
132
        return $this;
133
    }
134
135
    /**
136
     * @param ListenerInterface $listener
137
     * @return $this
138
     */
139
    public function addListener(ListenerInterface $listener)
140
    {
141
        if ($listener instanceof LoggerAwareInterface) {
142
            $listener->setLogger($this->logger);
143
        }
144
        $this->listeners[] = $listener;
145
        return $this;
146
    }
147
}
148