Completed
Push — master ( ea8464...30c3c3 )
by WEBEWEB
01:20
created

RepositoryHelper   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 169
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 7
dl 0
loc 169
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A executeStatement() 0 22 2
A getRepositoryReportSortClosure() 0 11 2
A prepareStatement() 0 9 1
A readRepositories() 0 19 3
A readRepository() 0 27 4
1
<?php
2
3
/*
4
 * This file is part of the core-bundle package.
5
 *
6
 * (c) 2019 WEBEWEB
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace WBW\Bundle\CoreBundle\Repository;
13
14
use Doctrine\DBAL\DBALException;
15
use Doctrine\DBAL\Driver\Statement;
16
use Doctrine\ORM\EntityManagerInterface;
17
use Doctrine\ORM\Mapping\ClassMetadata;
18
use Doctrine\ORM\Mapping\MappingException;
19
use WBW\Bundle\CoreBundle\Model\RepositoryReport;
20
use WBW\Bundle\CoreBundle\Service\EntityManagerTrait;
21
22
/**
23
 * Repository helper.
24
 *
25
 * @author webeweb <https://github.com/webeweb/>
26
 * @package WBW\Bundle\CoreBundle\Repository
27
 */
28
class RepositoryHelper {
29
30
    use EntityManagerTrait;
31
32
    /**
33
     * Service name.
34
     *
35
     * @var string
36
     */
37
    const SERVICE_NAME = "wbw.core.repository.repository_helper";
38
39
    /**
40
     * SQL query.
41
     *
42
     * @var string
43
     */
44
    const SQL_QUERY = <<< EOT
45
SELECT
46
    '%table%' AS 'table',
47
    '%entity%' AS 'entity',
48
    '%column%' AS 'column',
49
    '%field%' AS 'field',
50
    %available% AS 'available',
51
    MIN(LENGTH(`%column%`)) AS 'minimum',
52
    MAX(LENGTH(`%column%`)) AS 'maximum',
53
    AVG(LENGTH(`%column%`)) AS 'average',
54
    COUNT(`%column%`) AS 'count'
55
FROM `%table%`
56
EOT;
57
58
    /**
59
     * Constructor.
60
     *
61
     * @param EntityManagerInterface $entityManager The entity manager.
62
     */
63
    public function __construct(EntityManagerInterface $entityManager) {
64
        $this->setEntityManager($entityManager);
65
    }
66
67
    /**
68
     * Execute a statement.
69
     *
70
     * @param Statement $statement The statement.
71
     * @return RepositoryReport|null Returns the repository report in case of success, null otherwise.
72
     */
73
    protected function executeStatement(Statement $statement) {
74
75
        $result = $statement->execute();
76
        if (false === $result) {
77
            return null;
78
        }
79
80
        $row = $statement->fetchAll()[0];
81
82
        $model = new RepositoryReport();
83
        $model->setAvailable(intval($row["available"]));
84
        $model->setAverage(floatval($row["average"]));
85
        $model->setColumn($row["column"]);
86
        $model->setCount(intval($row["count"]));
87
        $model->setEntity($row["entity"]);
88
        $model->setField($row["field"]);
89
        $model->setMaximum(intval($row["maximum"]));
90
        $model->setMinimum(intval($row["minimum"]));
91
        $model->setTable($row["table"]);
92
93
        return $model;
94
    }
95
96
    /**
97
     * Get a repository report sort closure.
98
     *
99
     * @return Closure Returns the repository report sort closure.
100
     */
101
    public static function getRepositoryReportSortClosure() {
102
103
        return function(RepositoryReport $a, RepositoryReport $b) {
104
105
            if ($a->getEntity() === $b->getEntity()) {
106
                return strcmp($a->getField(), $b->getField());
107
            }
108
109
            return strcmp($a->getEntity(), $b->getEntity());
110
        };
111
    }
112
113
    /**
114
     * Prepare a statement.
115
     *
116
     * @param string $table The table.
117
     * @param string $entity The entity.
118
     * @param string $field The field.
119
     * @param int $available The available.
120
     * @param string $column The column.
121
     * @return Statement Returns the statement.
122
     * @throws DBALException Throws a DBAL exception.
123
     */
124
    protected function prepareStatement($table, $entity, $field, $available, $column) {
125
126
        $searches = ["%table%", "%entity%", "%field%", "%available%", "%column%"];
127
        $replaces = [$table, $entity, $field, $available, $column];
128
129
        $query = str_replace($searches, $replaces, self::SQL_QUERY);
130
131
        return $this->getEntityManager()->getConnection()->prepare($query);
132
    }
133
134
    /**
135
     * Read the repositories.
136
     *
137
     * @return RepositoryReport[] Returns the repository reports.
138
     * @throws DBALException Throws a DBAL exception.
139
     * @throws MappingException Throws a mapping exception.
140
     */
141
    public function readRepositories() {
142
143
        /** @var RepositoryReport[] $reports */
144
        $reports = [];
145
146
        /** @var ClassMetadata[] $allMetadata */
147
        $allMetadata = $this->getEntityManager()->getMetadataFactory()->getAllMetadata();
148
149
        foreach ($allMetadata as $current) {
150
            if (true === $current->isMappedSuperclass) {
151
                continue;
152
            }
153
            $reports = array_merge($reports, $this->readRepository($current));
154
        }
155
156
        usort($reports, static::getRepositoryReportSortClosure());
157
158
        return $reports;
159
    }
160
161
    /**
162
     * Read a repository.
163
     *
164
     * @param ClassMetadata $classMetadata The class metadata.
165
     * @return RepositoryReport[] Returns the repository reports.
166
     * @throws DBALException Throws a DBAL exception.
167
     * @throws MappingException Throws a mapping exception.
168
     */
169
    protected function readRepository(ClassMetadata $classMetadata) {
170
171
        /** @var RepositoryReport[] $reports */
172
        $reports = [];
173
174
        foreach ($classMetadata->getFieldNames() as $current) {
175
176
            $fieldMapping = $classMetadata->getFieldMapping($current);
177
            if (false === in_array($fieldMapping["type"], ["string", "text"])) {
178
                continue;
179
            }
180
181
            $args = [
182
                $classMetadata->getTableName(),
183
                $classMetadata->getName(),
184
                $fieldMapping["fieldName"],
185
                true === array_key_exists("length", $fieldMapping) ? $fieldMapping["length"] : -1,
186
                $fieldMapping["columnName"],
187
            ];
188
189
            $stmt = $this->prepareStatement($args[0], $args[1], $args[2], $args[3], $args[4]);
190
191
            $reports[] = $this->executeStatement($stmt);
192
        }
193
194
        return $reports;
195
    }
196
}
197