Test Setup Failed
Branch master (cd85d0)
by Valery
09:54
created

UpdateCommand::printMessage()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 5
c 1
b 0
f 0
nc 2
nop 4
dl 0
loc 8
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Command;
6
7
use App\Entity\Profile;
8
use App\Entity\PropertyDescription;
9
use App\Repository\PropertyRepository;
10
use App\Repository\UserRepository;
11
use Doctrine\ORM\EntityManagerInterface;
12
use Symfony\Component\Console\Command\Command;
13
use Symfony\Component\Console\Input\ArrayInput;
14
use Symfony\Component\Console\Input\InputInterface;
15
use Symfony\Component\Console\Output\OutputInterface;
16
use Symfony\Component\Console\Style\SymfonyStyle;
17
18
final class UpdateCommand extends Command
19
{
20
    private $entityManager;
21
    protected static $defaultName = 'app:update';
22
    protected static $defaultDescription = 'Application Update Assistant (1.8.1 -> 1.9.0)';
23
    private $propertyRepository;
24
    private $userRepository;
25
26
    public function __construct(
27
        EntityManagerInterface $entityManager,
28
        PropertyRepository $propertyRepository,
29
        UserRepository $userRepository,
30
        string $name = null
31
    ) {
32
        parent::__construct($name);
33
        $this->entityManager = $entityManager;
34
        $this->propertyRepository = $propertyRepository;
35
        $this->userRepository = $userRepository;
36
    }
37
38
    protected function execute(InputInterface $input, OutputInterface $output): int
39
    {
40
        if (0 !== $this->runMigrations($output)) {
41
            return Command::FAILURE;
42
        }
43
44
        try {
45
            $this->moveUserDataToProfile();
46
            $this->movePropertyDescription();
47
            $this->dropExtraColumns();
48
            $this->printMessage('success', $input, $output);
49
        } catch (\Exception $exception) {
50
            $this->printMessage('fail', $input, $output, $exception->getMessage());
51
52
            return Command::FAILURE;
53
        }
54
55
        return Command::SUCCESS;
56
    }
57
58
    private function runMigrations(OutputInterface $output): int
59
    {
60
        $consoleInput = new ArrayInput([]);
61
        $consoleInput->setInteractive(false);
62
        $this->getApplication()
63
            ->find('doctrine:migrations:migrate')
64
            ->run($consoleInput, $output);
65
66
        return Command::SUCCESS;
67
    }
68
69
    private function movePropertyDescription()
70
    {
71
        $properties = $this->findPropertiesWithoutDescription();
72
73
        foreach ($properties as $propertiy) {
74
            $this->createDescription($propertiy);
75
        }
76
    }
77
78
    private function moveUserDataToProfile()
79
    {
80
        $users = $this->findUsersWithoutProfile();
81
82
        foreach ($users as $user) {
83
            $this->createProfile($user);
84
        }
85
    }
86
87
    private function createProfile(array $user)
88
    {
89
        $profile = (new Profile())
90
            ->setUser($this->userRepository->find($user['id']))
0 ignored issues
show
Bug introduced by
It seems like $this->userRepository->find($user['id']) can also be of type null; however, parameter $user of App\Entity\Profile::setUser() does only seem to accept App\Entity\User, maybe add an additional type check? ( Ignorable by Annotation )

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

90
            ->setUser(/** @scrutinizer ignore-type */ $this->userRepository->find($user['id']))
Loading history...
91
            ->setFullName($user['full_name'])
92
            ->setPhone($user['phone']);
93
94
        $this->save($profile);
95
    }
96
97
    private function findUsersWithoutProfile()
98
    {
99
        $sql = 'SELECT id, full_name, phone FROM users WHERE id NOT IN (SELECT user_id FROM profile)';
100
101
        return $this->executeSql($sql)->fetchAll();
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\ForwardCom...lity\Result::fetchAll() has been deprecated: Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead. ( Ignorable by Annotation )

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

101
        return /** @scrutinizer ignore-deprecated */ $this->executeSql($sql)->fetchAll();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
102
    }
103
104
    private function findPropertiesWithoutDescription()
105
    {
106
        $sql = 'SELECT id, title, content, meta_title, meta_description
107
                    FROM property
108
                    WHERE id
109
                    NOT IN (SELECT property_id FROM property_description)';
110
111
        return $this->executeSql($sql)->fetchAll();
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\ForwardCom...lity\Result::fetchAll() has been deprecated: Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead. ( Ignorable by Annotation )

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

111
        return /** @scrutinizer ignore-deprecated */ $this->executeSql($sql)->fetchAll();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
112
    }
113
114
    private function createDescription(array $property)
115
    {
116
        $profile = (new PropertyDescription())
117
            ->setProperty($this->propertyRepository->find($property['id']))
0 ignored issues
show
Bug introduced by
It seems like $this->propertyRepository->find($property['id']) can also be of type null; however, parameter $property of App\Entity\PropertyDescription::setProperty() does only seem to accept App\Entity\Property, maybe add an additional type check? ( Ignorable by Annotation )

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

117
            ->setProperty(/** @scrutinizer ignore-type */ $this->propertyRepository->find($property['id']))
Loading history...
118
            ->setTitle($property['title'])
119
            ->setContent($property['content'])
120
            ->setMetaTitle($property['meta_title'])
121
            ->setMetaDescription($property['meta_description']);
122
123
        $this->save($profile);
124
    }
125
126
    private function dropExtraColumns(): void
127
    {
128
        $this->executeSql('ALTER TABLE users DROP full_name');
129
        $this->executeSql('ALTER TABLE users DROP phone');
130
        $this->executeSql('ALTER TABLE property DROP title');
131
        $this->executeSql('ALTER TABLE property DROP content');
132
        $this->executeSql('ALTER TABLE property DROP meta_title');
133
        $this->executeSql('ALTER TABLE property DROP meta_description');
134
    }
135
136
    private function printMessage(string $type, $input, $output, $message = ''): void
137
    {
138
        $io = new SymfonyStyle($input, $output);
139
        $io->success('Database schema updated successfully!');
140
141
        'success' === $type
142
            ? $io->success('Database schema updated successfully!')
143
            : $io->error($message);
144
    }
145
146
    private function save($entity): void
147
    {
148
        $this->entityManager->persist($entity);
149
        $this->entityManager->flush();
150
    }
151
152
    private function executeSql($sql)
153
    {
154
        $connection = $this->entityManager->getConnection();
155
        $query = $connection->prepare($sql);
156
157
        return $query->executeQuery();
158
    }
159
}
160