Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Pull Request — dev-extbase-fluid (#771)
by
unknown
03:16
created

DatabaseDocCommand::getTableInfo()   B

Complexity

Conditions 7
Paths 8

Size

Total Lines 52
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 32
c 1
b 0
f 0
nc 8
nop 2
dl 0
loc 52
rs 8.4746

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
5
 *
6
 * This file is part of the Kitodo and TYPO3 projects.
7
 *
8
 * @license GNU General Public License version 3 or later.
9
 * For the full copyright and license information, please read the
10
 * LICENSE.txt file that was distributed with this source code.
11
 */
12
13
namespace Kitodo\Dlf\Command;
14
15
use Doctrine\DBAL\Schema\Table;
16
use Kitodo\Dlf\Command\BaseCommand;
17
use Kitodo\Dlf\Common\DbDocs\RstSection;
18
use Kitodo\Dlf\Common\Doc;
19
use Kitodo\Dlf\Common\Helper;
20
use Kitodo\Dlf\Domain\Model\Document;
21
use ReflectionClass;
22
use Symfony\Component\Console\Input\InputInterface;
23
use Symfony\Component\Console\Input\InputOption;
24
use Symfony\Component\Console\Output\OutputInterface;
25
use Symfony\Component\Console\Style\SymfonyStyle;
26
use TYPO3\CMS\Core\Database\Schema\Parser\Parser;
27
use TYPO3\CMS\Core\Database\Schema\SqlReader;
28
use TYPO3\CMS\Core\Utility\GeneralUtility;
29
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
30
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
31
use TYPO3\CMS\Extbase\Object\ObjectManager;
32
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
33
use TYPO3\CMS\Extbase\Reflection\DocCommentParser;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Reflection\DocCommentParser was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
34
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
35
36
/**
37
 * CLI command for generating database documentation.
38
 */
39
class DatabaseDocCommand extends BaseCommand
40
{
41
    /**
42
     * Default output path for generated documentation file.
43
     */
44
    protected $defaultOutputPath = 'EXT:dlf/Documentation/Developers/Database.rst';
45
46
    /**
47
     * @var ObjectManager
48
     */
49
    protected $objectManager;
50
51
    /**
52
     * @var DataMapper
53
     */
54
    protected $dataMapper;
55
56
    /**
57
     * Configure the command by defining the name, options and arguments
58
     */
59
    public function configure()
60
    {
61
        $this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
62
        $this->dataMapper = $this->objectManager->get(DataMapper::class);
63
64
        $this
65
            ->setDescription('Aggregate database documentation from doc-comments, SQL COMMENT fields and TCA labels')
66
            ->setHelp('')
67
            ->addOption(
68
                'output',
69
                'o',
70
                InputOption::VALUE_OPTIONAL,
71
                'Path of the output documentation file. Default: ' . $this->defaultOutputPath
72
            );
73
    }
74
75
    /**
76
     * Execute the command.
77
     */
78
    protected function execute(InputInterface $input, OutputInterface $output)
79
    {
80
        $outputPath = $input->getOption('output') ?? GeneralUtility::getFileAbsFileName($this->defaultOutputPath);
81
82
        $io = new SymfonyStyle($input, $output);
83
        $io->title($this->getDescription());
84
85
        $tables = $this->collectTables();
86
        $page = $this->generatePage($tables);
87
88
        file_put_contents($outputPath, $page->render());
89
90
        $io->success('All done!');
91
92
        return 0;
93
    }
94
95
    /**
96
     * Collect information about relevant tables from `ext_tables.sql` and the
97
     * Extbase classmap.
98
     */
99
    protected function collectTables(): array
100
    {
101
        $sqlReader = GeneralUtility::makeInstance(SqlReader::class);
102
        $sqlCode = $sqlReader->getTablesDefinitionString(true);
103
        $createTableStatements = $sqlReader->getCreateTableStatementArray($sqlCode);
104
105
        $tableToClassName = $this->getTableClassMap();
106
107
        $result = [];
108
109
        foreach ($createTableStatements as $statement) {
110
            $parser = new Parser($statement);
111
            list($table) = $parser->parse();
112
113
            $tableName = $table->getName();
114
            if (!str_starts_with($tableName, 'tx_dlf_')) {
115
                continue;
116
            }
117
118
            $className = $tableToClassName[$tableName] ?? null;
119
120
            $result[] = $this->getTableInfo($table, $className);
121
        }
122
123
        return $result;
124
    }
125
126
    /**
127
     * Collect information about a single table.
128
     *
129
     * @param Table $table The table to be analyzed
130
     * @param string|null $className Fully qualified name of the domain model class
131
     */
132
    protected function getTableInfo(Table $table, ?string $className): object
133
    {
134
        $tableName = $table->getName();
135
136
        $isPrimary = [];
137
        if (!is_null($primaryKey = $table->getPrimaryKey())) {
138
            foreach ($primaryKey->getUnquotedColumns() as $primaryColumn) {
139
                $isPrimary[$primaryColumn] = true;
140
            }
141
        }
142
143
        $columns = [];
144
        foreach ($table->getColumns() as $column) {
145
            $columnName = $column->getName();
146
147
            $columns[$columnName] = (object) [
148
                'name' => $columnName,
149
                'type' => $column->getType(),
150
                'isPrimary' => isset($isPrimary[$columnName]),
151
                'sqlComment' => $column->getComment() ?? '',
152
                'fieldComment' => '',
153
                'feComment' => LocalizationUtility::translate($GLOBALS['TCA'][$tableName]['columns'][$columnName]['label'] ?? '') ?? '',
154
            ];
155
        }
156
157
        $result = (object) [
158
            'name' => $tableName,
159
            'columns' => $columns,
160
            'modelClass' => null,
161
            'sqlComment' => $table->getComment() ?? '',
162
            'classComment' => '',
163
            'feComment' => LocalizationUtility::translate($GLOBALS['TCA'][$tableName]['ctrl']['title'] ?? '') ?? '',
164
        ];
165
166
        // Integrate doc-comments from model class and its fields
167
        if ($className !== null) {
168
            $reflection = new ReflectionClass($className);
169
170
            $dataMap = $this->dataMapper->getDataMap($className);
171
172
            foreach ($reflection->getProperties() as $property) {
173
                $column = $dataMap->getColumnMap($property->getName());
174
                if ($column !== null) {
175
                    $result->columns[$column->getColumnName()]->fieldComment = $this->parseDocComment($property->getDocComment());
176
                }
177
            }
178
179
            $result->modelClass = $className;
180
            $result->classComment = $this->parseDocComment($reflection->getDocComment());
181
        }
182
183
        return $result;
184
    }
185
186
    protected function parseDocComment($docComment)
187
    {
188
        $fieldDocParser = new DocCommentParser();
189
        $fieldDocParser->parseDocComment($docComment);
190
191
        $text = $fieldDocParser->getDescription();
192
        $lines = explode("\n", $text);
193
        $lines = array_map(function ($line) {
194
            // There may be a single non-signifying space after the doc-comment asterisk
195
            return $line[0] === ' '
196
                ? substr($line, 1)
197
                : $line;
198
        }, $lines);
199
        $text = implode("\n", $lines);
200
201
        return $text;
202
    }
203
204
    /**
205
     * Get a map from database table names to their domain model class names.
206
     */
207
    protected function getTableClassMap(): array
208
    {
209
        Helper::polyfillExtbaseClassesForTYPO3v9();
0 ignored issues
show
Deprecated Code introduced by
The function Kitodo\Dlf\Common\Helper...baseClassesForTYPO3v9() has been deprecated: Remove once we drop support for TYPO3v9 ( Ignorable by Annotation )

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

209
        /** @scrutinizer ignore-deprecated */ Helper::polyfillExtbaseClassesForTYPO3v9();

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...
210
211
        $configurationManager = $this->objectManager->get(ConfigurationManager::class);
0 ignored issues
show
Deprecated Code introduced by
The function TYPO3\CMS\Extbase\Object\ObjectManager::get() has been deprecated: since TYPO3 10.4, will be removed in version 12.0 ( Ignorable by Annotation )

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

211
        $configurationManager = /** @scrutinizer ignore-deprecated */ $this->objectManager->get(ConfigurationManager::class);

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...
212
        $frameworkConfiguration = $configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
213
214
        $result = [];
215
216
        foreach ($frameworkConfiguration['persistence']['classes'] as $className => $tableConf) {
217
            // Check that the class is ours. This is relevant if some other extension
218
            // such as slub_digitalcollections adds its own model of a tx_dlf_* table.
219
            if (!str_starts_with($className, 'Kitodo\\Dlf\\')) {
220
                continue;
221
            }
222
223
            $tableName = $tableConf['mapping']['tableName'];
224
            $result[$tableName] = $className;
225
        }
226
227
        return $result;
228
    }
229
230
    /**
231
     * Transform table structure into .rst page.
232
     */
233
    protected function generatePage(array $tables)
234
    {
235
        $page = new RstSection();
236
        $page->setHeader('Database Tables');
237
        $page->addText(<<<RST
238
This is a reference of all database tables defined by Kitodo.Presentation.
239
240
.. tip:: This page is auto-generated. If you would like to edit it, please use doc-comments in the model class, COMMENT fields in ``ext_tables.sql`` if the table does not have one, or TCA labels. Then, you may re-generate the page by running ``typo3 kitodo:dbdocs`` in an installation of Kitodo.Presentation (e.g., within a DDEV container).
241
RST);
242
243
        // Sort tables alphabetically
244
        usort($tables, function ($lhs, $rhs) {
245
            return $lhs->name <=> $rhs->name;
246
        });
247
248
        foreach ($tables as $tableInfo) {
249
            $section = $page->subsection();
250
251
            // Set header
252
            $header = $tableInfo->name;
253
            if (!empty($tableInfo->feComment)) {
254
                $header .= ': ' . $tableInfo->feComment;
255
            }
256
            $section->setHeader($header);
257
258
            // Set introductory text of subsection
259
            if ($tableInfo->modelClass) {
260
                $section->addText('Extbase domain model: ``' . $tableInfo->modelClass . '``');
261
            }
262
            $section->addText($tableInfo->classComment);
263
            $section->addText($tableInfo->sqlComment);
264
265
            // Generate main table
266
            $header = [[
267
                'field' => 'Field',
268
                'description' => 'Description',
269
            ]];
270
271
            $rows = array_map(function ($column) use ($page) {
272
                return [
273
                    'field' => (
274
                        $page->format($column->name, ['bold' => $column->isPrimary])
275
                        . "\u{00a0}\u{00a0}"
276
                        . $page->format($column->type->getName(), ['italic' => true])
277
                    ),
278
279
                    'description' => $page->paragraphs([
280
                        $page->format($column->feComment, ['italic' => true]),
281
                        $column->fieldComment,
282
                        $column->sqlComment,
283
                    ]),
284
                ];
285
            }, $tableInfo->columns);
286
287
            $section->addTable($rows, $header);
288
        }
289
290
        return $page;
291
    }
292
}
293