1 | <?php |
||
35 | class FetchCommand extends Command |
||
36 | { |
||
37 | /** |
||
38 | * @var EventDispatcherInterface |
||
39 | */ |
||
40 | protected $eventDispatcher; |
||
41 | |||
42 | /** |
||
43 | * @var ManagerInterface |
||
44 | */ |
||
45 | protected $manager; |
||
46 | |||
47 | /** |
||
48 | * @var SourcesRegistryInterface |
||
49 | */ |
||
50 | protected $sourcesRegistry; |
||
51 | |||
52 | /** |
||
53 | * @var SymfonyStyle |
||
54 | */ |
||
55 | protected $output; |
||
56 | |||
57 | 9 | public function __construct(EventDispatcherInterface $eventDispatcher, ManagerInterface $manager, SourcesRegistryInterface $sourcesRegistry) |
|
64 | |||
65 | /** |
||
66 | * {@inheritdoc} |
||
67 | */ |
||
68 | 9 | protected function configure() |
|
81 | |||
82 | /** |
||
83 | * {@inheritdoc} |
||
84 | */ |
||
85 | 9 | protected function execute(InputInterface $input, OutputInterface $output) |
|
86 | { |
||
87 | 9 | $this->output = new SymfonyStyle($input, $output); |
|
88 | 9 | $date = (null !== $input->getOption('date')) ? $this->sanitizeDate($input->getOption('date')) : new \DateTime('now'); |
|
89 | 8 | $sources = $this->sanitizeSources($input->getOption('source')); |
|
90 | 7 | $this->output->title(sprintf('Fetching rates for sources "%s" on "%s".', implode('", "', $sources), $date->format('Y-m-d'))); |
|
91 | |||
92 | 7 | $errors = []; |
|
93 | 7 | $fetched = []; |
|
94 | |||
95 | 7 | foreach ($sources as $source) { |
|
|
|||
96 | |||
97 | try { |
||
98 | 7 | $rates = $this->manager->fetch($source, $date); |
|
99 | |||
100 | 7 | if (0 === count($rates)) { |
|
101 | 3 | throw new RuntimeException(sprintf('No rate fetched from source "%s".', $source)); |
|
102 | } |
||
103 | |||
104 | 6 | $rows = array_map(function(RateInterface $rate) { |
|
105 | return [ |
||
106 | 6 | $rate->getCurrencyCode(), |
|
107 | 6 | $rate->getRateType(), |
|
108 | 6 | $rate->getValue(), |
|
109 | ]; |
||
110 | 6 | }, $rates); |
|
111 | |||
112 | 6 | $this->output->section(sprintf('Fetched rates for source "%s":', $source)); |
|
113 | 6 | $this->output->table(['Currency code', 'Rate type', 'Value'], $rows); |
|
114 | |||
115 | 6 | $fetched[$source] = $rates; |
|
116 | |||
117 | 3 | } catch (\Exception $e) { |
|
118 | 3 | $this->output->error(sprintf('Could not fetch rates from source "%s" (%s).', $source, $e->getMessage())); |
|
119 | 7 | $errors[$source] = $e; |
|
120 | } |
||
121 | } |
||
122 | |||
123 | 7 | if (!$input->getOption('silent')) { |
|
124 | |||
125 | 6 | if (count($fetched) > 0) { |
|
126 | 5 | $this->eventDispatcher->dispatch(FetchEvents::SUCCESS, new FetchSuccessEvent($fetched, $date)); |
|
127 | } |
||
128 | |||
129 | 6 | if (count($errors) > 0) { |
|
130 | 2 | $this->eventDispatcher->dispatch(FetchEvents::ERROR, new FetchErrorEvent($errors, $date)); |
|
131 | } |
||
132 | } |
||
133 | |||
134 | 7 | if ($errors) { |
|
135 | 3 | $this->output->error('Could not fetch all rates.'); |
|
136 | 3 | return -1; |
|
137 | } |
||
138 | |||
139 | 4 | $this->output->success('Rates successfully fetched.'); |
|
140 | 4 | return 0; |
|
141 | } |
||
142 | |||
143 | /** |
||
144 | * Sanitizes a date from console input. |
||
145 | * |
||
146 | * @param string|\DateTime $dateString A date |
||
147 | * |
||
148 | * @return \DateTime |
||
149 | * |
||
150 | * @throws InvalidArgumentException |
||
151 | */ |
||
152 | 2 | protected function sanitizeDate($dateString) |
|
174 | |||
175 | /** |
||
176 | * Clean sources from console input. |
||
177 | * |
||
178 | * @param mixed $sourcesString A sources. |
||
179 | * |
||
180 | * @return array|null |
||
181 | * |
||
182 | * @throws InvalidArgumentException |
||
183 | */ |
||
184 | 8 | protected function sanitizeSources($sourcesString) |
|
207 | } |
||
208 |
There are different options of fixing this problem.
If you want to be on the safe side, you can add an additional type-check:
If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:
Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.