Test Failed
Push — main ( df6632...4291e6 )
by Alex
04:31
created

ImportDataFromCsvCommand::configure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 6
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 8
ccs 7
cts 7
cp 1
crap 1
rs 10
1
<?php
2
3
namespace App\Command;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use Doctrine\Persistence\ManagerRegistry;
7
use Doctrine\Persistence\ObjectManager;
8
use Symfony\Component\Console\Attribute\AsCommand;
9
use Symfony\Component\Console\Command\Command;
10
use Symfony\Component\Console\Input\InputArgument;
11
use Symfony\Component\Console\Input\InputInterface;
12
use Symfony\Component\Console\Input\InputOption;
13
use Symfony\Component\Console\Output\OutputInterface;
14
use Symfony\Component\Console\Style\SymfonyStyle;
15
use Symfony\Component\HttpKernel\KernelInterface;
16
use InvalidArgumentException;
17
18
#[AsCommand(
19
    name: 'app:import-csv',
20
    description: 'Import data from a CSV file into the database.',
21
    hidden: false,
22
    aliases: ['app:import-data', 'app:import-csv-file']
23
)]
24
class ImportDataFromCsvCommand extends Command
25
{
26
    /**
27
     * @var EntityManagerInterface|ObjectManager
28
    */
29
    private $entityManager;
30
31
    /**
32
     * @var ManagerRegistry
33
     */
34
    private $doctrine;
35
36
    /**
37
     * @var KernelInterface
38
     */
39
    private $kernel;
40
41
    /**
42
     * ImportDataCommand constructor.
43
     *
44
     * @param ManagerRegistry $doctrine
45
     * @param KernelInterface $kernel
46
     */
47 4
    public function __construct(ManagerRegistry $doctrine, KernelInterface $kernel)
48
    {
49 4
        $this->entityManager = $doctrine->getManager();
50 4
        $this->doctrine = $doctrine;
51 4
        $this->kernel = $kernel;
52 4
        parent::__construct();
53
    }
54
55
    /**
56
     * Configures the command.
57
     */
58 4
    protected function configure(): void
59
    {
60 4
        $this
61 4
            ->setName('app:import-data')
62 4
            ->setHelp('This command allows you to import data from a CSV file into the database')
63 4
            ->setDescription('Import data from a CSV file into the database.')
64 4
            ->addArgument('filename', InputArgument::REQUIRED, 'The name of the CSV file (without the directory).')
65 4
            ->addOption('manager', 'm', InputOption::VALUE_REQUIRED, 'The name of the EntityManager service to use.', 'default');
66
    }
67
68
    /**
69
     * Executes the command to import data from the CSV file.
70
     *
71
     * @param InputInterface  $input  The input interface.
72
     * @param OutputInterface $output The output interface.
73
     *
74
     * @return int The command exit code.
75
     */
76 4
    protected function execute(InputInterface $input, OutputInterface $output)
77
    {
78 4
        $io = new SymfonyStyle($input, $output);
79
80
        /** @var string */
81 4
        $filename = $input->getArgument('filename'); // Retrieve the argument value
82
83
        /** @var string */
84 4
        $csvDirectory = $this->kernel->getProjectDir() . '/' . 'public/csv/';
85 4
        $csvFile = $csvDirectory . $filename;
86
87
        // Check if file exists
88 4
        if (!file_exists($csvFile)) {
89 1
            $io->error(sprintf('The CSV file "%s" does not exist.', $csvFile));
90 1
            return Command::FAILURE;
91
        }
92
93
        // Provide feedback to user
94 3
        $output->writeln([
95 3
            'Importing CSV',
96 3
            '=============',
97 3
            'Filename: ' . $filename,
98 3
            'CSV File: ' . $csvFile
99 3
        ]);
100
101
        // Parse CSV file into array of fields
102
        /** @var string[] */
103 3
        $fileAsArray = file($csvFile);
104 3
        $csvData = array_map('str_getcsv', $fileAsArray);
105
106
        // Shift off first value of the array, i.e. the headers
107
        /** @var string[] */
108 3
        $headers = array_shift($csvData);
109
110
        /** @var string */
111 3
        $entityManagerName = $input->getOption('manager');
112
113
        try {
114 3
            $entityManager = $this->doctrine->getManager($entityManagerName);
115 1
        } catch (InvalidArgumentException) {
116 1
            $io->error(sprintf('The Entity Manager "%s" does not exist.', $entityManagerName));
117 1
            return Command::FAILURE;
118
        }
119
120 2
        $this->entityManager = $entityManager;
121
122 2
        $output->writeln('Entity manager: ' . $entityManagerName);
123
124
        // Retrieve entity based on filename, e.g. location.csv will look for Location entity
125 2
        $entityClass = $this->getEntityClass($filename);
126
127 2
        if ($entityClass === null) {
128 1
            $io->error(sprintf('No entity class found for the CSV file "%s".', $filename));
129 1
            return Command::FAILURE;
130
        }
131
132 1
        $output->writeln(sprintf("Entity class '%s' found for file '%s'.", $entityClass, $filename));
133
134 1
        foreach ($csvData as $row) {
135 1
            $entity = new $entityClass();
136
137 1
            foreach ($row as $key => $value) {
138 1
                $property = $headers[$key];
139 1
                $setter = 'set' . ucfirst($property);
140
141 1
                if (method_exists($entity, $setter)) {
142 1
                    $value = ($value !== '') ? $value : null; // Convert empty strings to null
143 1
                    $entity->$setter($value);
144
                }
145
            }
146
147 1
            $entityManager->persist($entity);
148
        }
149
150 1
        $entityManager->flush();
151
152 1
        $io->success('Data imported successfully.');
153
154 1
        return Command::SUCCESS;
155
    }
156
157
    /**
158
     * Gets the entity class based on the provided CSV file name.
159
     *
160
     * @param string $filename The name of the CSV file.
161
     *
162
     * @return string|null The entity class name, or null if not found.
163
     */
164 2
    private function getEntityClass(string $filename): ?string
165
    {
166 2
        $entityName = basename($filename, '.csv');
167
168
        // Get the entity namespace based on the entity manager configuration
169
        /** @var EntityManagerInterface */
170 2
        $entityManager = $this->entityManager;
171 2
        $configuration = $entityManager->getConfiguration();
0 ignored issues
show
Bug introduced by
The method getConfiguration() does not exist on Doctrine\Persistence\ObjectManager. It seems like you code against a sub-type of said class. However, the method does not exist in Doctrine\Persistence\ObjectManagerDecorator. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

171
        /** @scrutinizer ignore-call */ 
172
        $configuration = $entityManager->getConfiguration();
Loading history...
172 2
        $entityNamespaces = $configuration->getEntityNamespaces();
173 2
        foreach ($entityNamespaces as $namespace) {
174 2
            $entityClass = $namespace . '\\' . ucfirst($entityName);
175
176 2
            if (class_exists($entityClass)) {
177 1
                return $entityClass;
178
            }
179
        }
180
181 1
        return null;
182
    }
183
}
184