Passed
Push — master ( 98954f...37aea2 )
by Andrea
16:13 queued 12s
created

DatabaseUtils::isSchemaChanged()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 12
nc 1
nop 0
dl 0
loc 21
ccs 11
cts 11
cp 1
crap 1
rs 9.8666
c 0
b 0
f 0
1
<?php
2
3
namespace Cdf\BiCoreBundle\Utils\Database;
4
5
use DateTime;
6
use Doctrine\ORM\EntityManagerInterface;
7
use Doctrine\ORM\EntityManager;
8
use Symfony\Component\HttpKernel\KernelInterface;
9
use Symfony\Bundle\FrameworkBundle\Console\Application;
10
use Symfony\Component\Console\Input\ArrayInput;
11
use Symfony\Component\Console\Output\BufferedOutput;
12
use \Exception;
13
use function count;
14
15
class DatabaseUtils
16
{
17
    /* @var $em EntityManager */
0 ignored issues
show
Documentation Bug introduced by
The doc comment $em at position 0 could not be parsed: Unknown type name '$em' at position 0 in $em.
Loading history...
18
19
    private EntityManagerInterface $em;
20
    private KernelInterface $kernel;
21
22 2
    public function __construct(KernelInterface $kernel, EntityManagerInterface $em)
23
    {
24 2
        $this->kernel = $kernel;
25 2
        $this->em = $em;
26 2
    }
27
28
    /**
29
     *
30
     * @param mixed $entity
31
     * @param string $field
32
     * @return string
33
     */
34 2
    public function getFieldType($entity, $field)
35
    {
36 2
        $classname = get_class($entity);
37 2
        if ($classname === false) {
38
            throw new Exception("Entity class not found: " . $entity);
39
        }
40 2
        $metadata = $this->em->getClassMetadata($classname);
41 2
        $fieldMetadata = $metadata->fieldMappings[$field];
42
43 2
        $fieldType = $fieldMetadata['type'];
44
45 2
        return $fieldType;
46
    }
47
48
    /**
49
     *
50
     * @param mixed $entity
51
     * @param string $fieldname
52
     * @param mixed $oldvalue
53
     * @param mixed $newvalue
54
     * @return bool
55
     */
56 1
    public function isRecordChanged($entity, $fieldname, $oldvalue, $newvalue)
57
    {
58 1
        $fieldtype = $this->getFieldType(new $entity(), $fieldname);
59 1
        if ('boolean' === $fieldtype) {
60 1
            return $oldvalue !== $newvalue;
61
        }
62 1
        if ('datetime' === $fieldtype || 'date' === $fieldtype) {
63 1
            return $this->isDateChanged($oldvalue, $newvalue);
64
        }
65 1
        if (is_array($oldvalue)) {
66 1
            return $this->isArrayChanged($oldvalue, $newvalue);
67
        }
68
69 1
        return $oldvalue !== $newvalue;
70
    }
71
72
    /**
73
     *
74
     * @param mixed $oldvalue
75
     * @param mixed $newvalue
76
     * @return boolean
77
     */
78 1
    public function isDateChanged($oldvalue, $newvalue)
79
    {
80 1
        $datenewvalue = new DateTime();
81 1
        $datenewvalue->setTimestamp($newvalue);
82 1
        $twoboth = !$oldvalue && !$newvalue;
83 1
        if ($twoboth) {
84 1
            return false;
85
        }
86 1
        $onlyonenull = (!$oldvalue && $newvalue) || ($oldvalue && !$newvalue);
87 1
        if ($onlyonenull) {
88
            return true;
89
        }
90 1
        $changed = ($oldvalue != $datenewvalue);
91
92 1
        return $changed;
93
    }
94
95
    /**
96
     *
97
     * @param mixed $oldvalue
98
     * @param mixed $newvalue
99
     * @return boolean
100
     */
101 1
    public function isArrayChanged($oldvalue, $newvalue)
102
    {
103 1
        $twoboth = !$oldvalue && !$newvalue;
104 1
        if ($twoboth) {
105
            return false;
106
        }
107 1
        $onlyonenull = (!$oldvalue && $newvalue) || ($oldvalue && !$newvalue);
108 1
        if ($onlyonenull) {
109 1
            return true;
110
        }
111 1
        $numdiff = array_diff($oldvalue, $newvalue);
112
113 1
        return count($numdiff) > 0;
114
    }
115
116
    /**
117
     *
118
     * @param string $entityclass
119
     * @param bool $cascade
120
     * @return mixed
121
     */
122 1
    public function truncateTable($entityclass, $cascade = false)
123
    {
124 1
        $cmd = $this->em->getClassMetadata($entityclass);
125 1
        $connection = $this->em->getConnection();
126 1
        $dbPlatform = $connection->getDatabasePlatform();
127 1
        $dbtype = $connection->getDriver()->getDatabasePlatform()->getName();
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Platforms\...ractPlatform::getName() has been deprecated: Identify platforms by their class. ( Ignorable by Annotation )

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

127
        $dbtype = /** @scrutinizer ignore-deprecated */ $connection->getDriver()->getDatabasePlatform()->getName();

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...
128 1
        $retval = false;
129
130 1
        switch ($dbtype) {
131 1
            case 'mysql':
132
                $connection->query('SET FOREIGN_KEY_CHECKS=0');
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Connection::query() has been deprecated: This API is deprecated and will be removed after 2022 ( Ignorable by Annotation )

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

132
                /** @scrutinizer ignore-deprecated */ $connection->query('SET FOREIGN_KEY_CHECKS=0');

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...
133
                $q = $dbPlatform->getTruncateTableSql($cmd->getTableName(), $cascade);
134
                $retval = $connection->executeUpdate($q);
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Connection::executeUpdate() has been deprecated: This API is deprecated and will be removed after 2022 ( Ignorable by Annotation )

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

134
                $retval = /** @scrutinizer ignore-deprecated */ $connection->executeUpdate($q);

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...
135
                $connection->query('SET FOREIGN_KEY_CHECKS=1');
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Connection::query() has been deprecated: This API is deprecated and will be removed after 2022 ( Ignorable by Annotation )

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

135
                /** @scrutinizer ignore-deprecated */ $connection->query('SET FOREIGN_KEY_CHECKS=1');

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...
136
                break;
137 1
            case 'postgresql':
138 1
                $cascadesql = $cascade ? 'CASCADE' : '';
139 1
                $tablename = $cmd->getTableName();
140 1
                if ($cmd->getSchemaName()) {
141
                    $tablename = $cmd->getSchemaName() . '.' . $tablename;
142
                }
143 1
                $retval = $connection->executeQuery(sprintf('TRUNCATE TABLE %s ' . $cascadesql, $tablename));
144 1
                break;
145
            default:
146
                $q = $dbPlatform->getTruncateTableSql($cmd->getTableName(), $cascade);
147
                $retval = $connection->executeUpdate($q);
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Connection::executeUpdate() has been deprecated: This API is deprecated and will be removed after 2022 ( Ignorable by Annotation )

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

147
                $retval = /** @scrutinizer ignore-deprecated */ $connection->executeUpdate($q);

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...
148
                break;
149
        }
150 1
        $this->em->clear();
151
152 1
        return $retval;
153
    }
154
155 2
    public function isSchemaChanged(): bool
156
    {
157 2
        $application = new Application($this->kernel);
158 2
        $application->setAutoExit(false);
159
160 2
        $input = new ArrayInput(array(
161 2
            'command' => 'doctrine:schema:update',
162
            '--dump-sql' => true,
163
            '--no-debug' => true,
164 2
            '--env' => $this->kernel->getEnvironment(),
165
        ));
166
167
        // You can use NullOutput() if you don't need the output
168 2
        $output = new BufferedOutput();
169 2
        $application->run($input, $output);
170
171
        // return the output, don't use if you used NullOutput()
172 2
        $content = $output->fetch();
173 2
        $changed = strpos($content, 'Nothing to update');
174
175 2
        return 0 !== $changed;
176
    }
177
}
178