ExportCommand::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
1
<?php
2
3
namespace MLD\Console\Command;
4
5
use MLD\Converter\AbstractConverter;
6
use Symfony\Component\Console\Command\Command;
7
use Symfony\Component\Console\Input\InputInterface;
8
use Symfony\Component\Console\Input\InputOption;
9
use Symfony\Component\Console\Output\OutputInterface;
10
11
/**
12
 * Class ExportCommand
13
 * @package MLD\Console\Command
14
 */
15
class ExportCommand extends Command
16
{
17
18
    /**
19
     * @var string
20
     */
21
    private $inputFile;
22
23
    /**
24
     * @var string
25
     */
26
    private $defaultOutputDirectory;
27
28
    /**
29
     * @var array
30
     */
31
    private $converters = [
32
        'json' => ['class' => '\MLD\Converter\JsonConverter', 'output_file' => 'countries.json'],
33
        'json_unescaped' => ['class' => '\MLD\Converter\JsonConverterUnicode', 'output_file' => 'countries-unescaped.json'],
34
        'csv' => ['class' => '\MLD\Converter\CsvConverter', 'output_file' => 'countries.csv'],
35
        'xml' => ['class' => '\MLD\Converter\XmlConverter', 'output_file' => 'countries.xml'],
36
        'yml' => ['class' => '\MLD\Converter\YamlConverter', 'output_file' => 'countries.yml'],
37
    ];
38
39
    /**
40
     * @var
41
     */
42
    private $outputFieldsCache;
43
44
    /**
45
     * @param string $inputFile Full path and filename of the input country data JSON file.
46
     * @param string $defaultOutputDirectory Full path to output directory for converted files.
47
     * @param string|null $name
48
     */
49
    public function __construct($inputFile, $defaultOutputDirectory, $name = 'convert')
50
    {
51
        $this->inputFile = $inputFile;
52
        $this->defaultOutputDirectory = $defaultOutputDirectory;
53
54
        parent::__construct($name);
55
    }
56
57
    /**
58
     * @inheritdoc
59
     */
60
    protected function configure()
61
    {
62
        $this
63
            ->setDescription('Converts source country data to various output formats')
64
            ->addOption(
65
                'exclude-field',
66
                'x',
67
                InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED,
68
                'If set, excludes top-level field with the given name from the output. Cannot be used with --include-field',
69
                []
70
            )
71
            ->addOption(
72
                'include-field',
73
                'i',
74
                InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED,
75
                'If set, include only these top-level fields with the given name from the output. Cannot be used with --exclude-field',
76
                []
77
            )
78
            ->addOption(
79
                'format',
80
                'f',
81
                InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED,
82
                'Output formats',
83
                array_keys($this->converters)
84
            )
85
            ->addOption(
86
                'output-dir',
87
                null,
88
                InputOption::VALUE_OPTIONAL | InputOption::VALUE_REQUIRED,
89
                'Directory where you want to put output files',
90
                $this->defaultOutputDirectory
91
            );
92
    }
93
94
    /**
95
     * @param InputInterface $input
96
     * @param OutputInterface $output
97
     * @return int|null|void
98
     */
99
    protected function execute(InputInterface $input, OutputInterface $output)
100
    {
101
        $countries = json_decode(file_get_contents($this->inputFile), true);
102
        $excludeFields = $input->getOption('exclude-field');
103
        $includeFields = $input->getOption('include-field');
104
        $formats = $input->getOption('format');
105
        $outputDirectory = $input->getOption('output-dir');
106
107
        foreach ($formats as $format) {
108
            $c = $this->converters[$format];
109
            if ($output->isVerbose()) {
110
                $output->writeln('Converting to ' . $format);
111
            }
112
113
            /** @var AbstractConverter $converter */
114
            $converter = new $c['class']($countries);
115
            $fields = $this->getOutputFields($converter->getFields(), $excludeFields, $includeFields);
116
117
            $converter
118
                ->setOutputDirectory($outputDirectory)
119
                ->setFields($fields)
120
                ->save($c['output_file']);
121
        }
122
123
        $count = count($formats);
124
        $output->writeln('Converted data for <info>' . count($countries) . '</info> countries into <info>' . $count . '</info> ' . ($count == 1 ? 'format.' : 'formats.'));
125
    }
126
127
    /**
128
     * @param array $baseFields
129
     * @param array $excludeFields
130
     * @param array $includeFields
131
     * @return array
132
     */
133
    private function getOutputFields($baseFields, $excludeFields, $includeFields)
134
    {
135
        if ($this->outputFieldsCache) {
136
            return $this->outputFieldsCache;
137
        }
138
139
        if (!empty($excludeFields)) {
140
            $this->outputFieldsCache = array_diff($baseFields, $excludeFields);
141
        } elseif (!empty($includeFields)) {
142
            $this->outputFieldsCache = array_intersect($baseFields, $includeFields);
143
        } else {
144
            $this->outputFieldsCache = $baseFields;
145
        }
146
147
        return $this->outputFieldsCache;
148
    }
149
}
150