Completed
Push — master ( b07376...497c09 )
by WEBEWEB
01:29
created

RepositoryReportHelper::executeStatement()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

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