Passed
Push — master ( 82544b...801c67 )
by WEBEWEB
02:59
created

RepositoryService::findAll()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
c 0
b 0
f 0
dl 0
loc 19
rs 10
cc 3
nc 3
nop 0
1
<?php
2
3
/*
4
 * This file is part of the core-bundle package.
5
 *
6
 * (c) 2022 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\Service;
13
14
use Doctrine\ORM\Mapping\ClassMetadata;
15
use PDO;
16
use Throwable;
17
use WBW\Library\Symfony\Model\RepositoryDetail;
18
use WBW\Library\Symfony\Model\RepositoryReport;
19
use WBW\Library\Symfony\Model\RepositoryReportInterface;
20
use WBW\Library\Types\Helper\ArrayHelper;
21
22
/**
23
 * Repository service.
24
 *
25
 * @author webeweb <https://github.com/webeweb>
26
 * @package WBW\Bundle\CoreBundle\Service
27
 */
28
class RepositoryService implements RepositoryServiceInterface {
29
30
    use StatementServiceTrait {
31
        setStatementService as public;
32
    }
33
34
    /**
35
     * Service name.
36
     *
37
     * @var string
38
     */
39
    const SERVICE_NAME = "wbw.core.service.repository";
40
41
    /**
42
     * {@inheritdoc}
43
     */
44
    public function findAll(): array {
45
46
        /** @var RepositoryReportInterface[] $reports */
47
        $reports = [];
48
49
        /** @var ClassMetadata[] $allMetadata */
50
        $allMetadata = $this->getStatementService()->getEntityManager()->getMetadataFactory()->getAllMetadata();
51
        foreach ($allMetadata as $current) {
52
53
            if (true === $current->isMappedSuperclass) {
54
                continue;
55
            }
56
57
            $reports[] = $this->findReport($current);
58
        }
59
60
        usort($reports, static::usortRepositoryReportCallback());
61
62
        return $reports;
63
    }
64
65
    /**
66
     * Find all repository details.
67
     *
68
     * @param ClassMetadata $classMetadata The class metadata.
69
     * @return RepositoryDetail[] Returns the repository details.
70
     * @throws Throwable Throws an exception if an error occurs.
71
     */
72
    protected function findDetails(ClassMetadata $classMetadata): array {
73
74
        /** @var RepositoryDetail[] $models */
75
        $models = [];
76
77
        foreach ($classMetadata->getFieldNames() as $current) {
78
79
            $fieldMapping = $classMetadata->getFieldMapping($current);
80
            if (false === in_array($fieldMapping["type"], ["string", "text"])) {
81
                continue;
82
            }
83
84
            $params = [
85
                $classMetadata->getTableName(),
86
                $classMetadata->getName(),
87
                $fieldMapping["columnName"],
88
                $fieldMapping["fieldName"],
89
                ArrayHelper::get($fieldMapping, "length", -1),
90
            ];
91
92
            $models[] = $this->newRepositoryDetail($params[0], $params[1], $params[2], $params[3], $params[4]);
93
        }
94
95
        return $models;
96
    }
97
98
    /**
99
     * Find one repository report.
100
     *
101
     * @param ClassMetadata $classMetadata The class metadata.
102
     * @return RepositoryReportInterface Returns the repository report.
103
     * @throws Throwable Throws an exception if an error occurs.
104
     */
105
    protected function findReport(ClassMetadata $classMetadata): RepositoryReportInterface {
106
107
        $query  = "SELECT COUNT(*) FROM {$classMetadata->getTableName()}";
108
        $result = $this->getStatementService()->executeQuery($query, []);
109
110
        $count = intval($result->fetchOne());
111
112
        $model = new RepositoryReport();
113
        $model->setTable($classMetadata->getTableName());
114
        $model->setEntity($classMetadata->getName());
115
        $model->setCount($count);
116
117
        $details = $this->findDetails($classMetadata);
118
        foreach ($details as $current) {
119
120
            if (null !== $current) {
121
                $model->addDetail($current->setRepositoryReport($model));
122
            }
123
        }
124
125
        return $model;
126
    }
127
128
    /**
129
     * Creates a repository detail.
130
     *
131
     * @param string $table The table.
132
     * @param string $entity The entity.
133
     * @param string $column The column.
134
     * @param string $field The field.
135
     * @param int $available The available.
136
     * @return RepositoryDetail Returns the repository detail.
137
     * @throws Throwable Throws an exception if an error occurs.
138
     */
139
    protected function newRepositoryDetail(string $table, string $entity, string $column, string $field, int $available): RepositoryDetail {
140
141
        $template = $this->getStatementService()->readStatementFile(__DIR__ . "/RepositoryService.sql");
142
143
        $searches = ["{{ table }}", "{{ column }}"];
144
        $replaces = [$table, $column];
145
146
        $sql = str_replace($searches, $replaces, $template);
147
148
        $stmt = $this->getStatementService()->prepareStatement($sql, [
149
            ":available" => [$available, PDO::PARAM_INT],
150
            ":column"    => [$column, PDO::PARAM_STR],
151
            ":entity"    => [$entity, PDO::PARAM_STR],
152
            ":field"     => [$field, PDO::PARAM_STR],
153
            ":table"     => [$table, PDO::PARAM_STR],
154
        ]);
155
156
        $result = $stmt->executeQuery();
157
158
        $row = $result->fetchAllAssociative()[0];
159
160
        $model = new RepositoryDetail();
161
        $model->setAvailable(intval($row["available"]));
162
        $model->setAverage(floatval($row["average"]));
163
        $model->setColumn($row["column"]);
164
        $model->setField($row["field"]);
165
        $model->setMaximum(intval($row["maximum"]));
166
        $model->setMinimum(intval($row["minimum"]));
167
168
        return $model;
169
    }
170
171
    /**
172
     * Usort repository report callback.
173
     *
174
     * @return callable Returns the usort repository report callback.
175
     */
176
    protected static function usortRepositoryReportCallback(): callable {
177
178
        return function(RepositoryReport $a, RepositoryReport $b): int {
179
            return strcmp($a->getEntity(), $b->getEntity());
0 ignored issues
show
Bug introduced by
It seems like $a->getEntity() can also be of type null; however, parameter $string1 of strcmp() does only seem to accept string, 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

179
            return strcmp(/** @scrutinizer ignore-type */ $a->getEntity(), $b->getEntity());
Loading history...
Bug introduced by
It seems like $b->getEntity() can also be of type null; however, parameter $string2 of strcmp() does only seem to accept string, 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

179
            return strcmp($a->getEntity(), /** @scrutinizer ignore-type */ $b->getEntity());
Loading history...
180
        };
181
    }
182
}
183