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
|
|
|
$this->applyProcessors($tile, $this->target); |
66
|
|
|
$this->notifyListeners($tile, $this->target); |
67
|
|
|
} |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* @param TileInterface $tile |
72
|
|
|
* @param SpecificationInterface $specification |
73
|
|
|
*/ |
74
|
|
View Code Duplication |
private function applyProcessors( |
|
|
|
|
75
|
|
|
TileInterface $tile, |
76
|
|
|
SpecificationInterface $specification |
77
|
|
|
) { |
78
|
|
|
foreach ($this->processors as $processors) { |
79
|
|
|
foreach ($processors as $processor) { |
80
|
|
|
$context = [ |
81
|
|
|
'tile' => $tile->getPosition(), |
82
|
|
|
'processor' => $processor |
83
|
|
|
]; |
84
|
|
|
$template = 'Applying processor {processor} to tile {tile}'; |
85
|
|
|
$this->logger->debug($template, $context); |
86
|
|
|
$processor->process($tile, $specification); |
87
|
|
|
} |
88
|
|
|
} |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* @param TileInterface $tile |
93
|
|
|
* @param SpecificationInterface $specification |
94
|
|
|
*/ |
95
|
|
View Code Duplication |
private function notifyListeners( |
|
|
|
|
96
|
|
|
TileInterface $tile, |
97
|
|
|
SpecificationInterface $specification |
98
|
|
|
) { |
99
|
|
|
foreach ($this->listeners as $listener) { |
100
|
|
|
$context = [ |
101
|
|
|
'tile' => $tile->getPosition(), |
102
|
|
|
'listener' => $listener |
103
|
|
|
]; |
104
|
|
|
$template = 'Applying listener {listener} to tile {tile}'; |
105
|
|
|
$this->logger->debug($template, $context); |
106
|
|
|
$listener->accept($tile, $specification); |
107
|
|
|
} |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* @param ProcessorInterface $processor |
112
|
|
|
* @param int $order Order in which processors are applied (lower order. |
113
|
|
|
* values force processors to be run earlier). Processor with same order |
114
|
|
|
* value will be run in the order they were added. |
115
|
|
|
* priority |
116
|
|
|
* |
117
|
|
|
* @return $this |
118
|
|
|
*/ |
119
|
|
|
public function addProcessor(ProcessorInterface $processor, $order = 0) |
120
|
|
|
{ |
121
|
|
|
if ($processor instanceof LoggerAwareInterface) { |
122
|
|
|
$processor->setLogger($this->logger); |
123
|
|
|
} |
124
|
|
|
if (!$this->processors[$order]) { |
125
|
|
|
$this->processors[$order] = []; |
126
|
|
|
} |
127
|
|
|
$this->processors[$order][] = $processor; |
128
|
|
|
ksort($this->processors); |
129
|
|
|
return $this; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* @param ListenerInterface $listener |
134
|
|
|
* @return $this |
135
|
|
|
*/ |
136
|
|
|
public function addListener(ListenerInterface $listener) |
137
|
|
|
{ |
138
|
|
|
if ($listener instanceof LoggerAwareInterface) { |
139
|
|
|
$listener->setLogger($this->logger); |
140
|
|
|
} |
141
|
|
|
$this->listeners[] = $listener; |
142
|
|
|
return $this; |
143
|
|
|
} |
144
|
|
|
} |
145
|
|
|
|
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.