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.

Issues (186)

Build/Documentation/dbdocs/Generator.php (1 issue)

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\DbDocs;
14
15
use Doctrine\DBAL\Schema\Table;
16
use Kitodo\Dlf\Common\Helper;
17
use ReflectionClass;
18
use TYPO3\CMS\Core\Database\Schema\Parser\Parser;
19
use TYPO3\CMS\Core\Database\Schema\SqlReader;
20
use TYPO3\CMS\Core\Localization\LanguageService;
21
use TYPO3\CMS\Core\Utility\GeneralUtility;
22
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
23
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
24
use TYPO3\CMS\Extbase\Object\ObjectManager;
25
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
26
27
/**
28
 * Aggregates information about database tables and generates an .rst reference page.
29
 *
30
 * @author Kajetan Dvoracek <[email protected]>
31
 * @package TYPO3
32
 * @subpackage dlf
33
 * @access public
34
 */
35
class Generator
36
{
37
    /**
38
     * @var LanguageService
39
     */
40
    protected $languageService;
41
42
    /**
43
     * @var DataMapper
44
     */
45
    protected $dataMapper;
46
47
    /**
48
     * @var SqlReader
49
     */
50
    protected $sqlReader;
51
52
    /**
53
     * @var ConfigurationManager
54
     */
55
    protected $configurationManager;
56
57
    /**
58
     * @param LanguageService $languageService
59
     */
60
    public function injectLanguageService(LanguageService $languageService)
61
    {
62
        $this->languageService = $languageService;
63
    }
64
65
    /**
66
     * @param DataMapper $dataMapper
67
     */
68
    public function injectDataMapper(DataMapper $dataMapper)
69
    {
70
        $this->dataMapper = $dataMapper;
71
    }
72
73
    /**
74
     * @param SqlReader $sqlReader
75
     */
76
    public function injectSqlReader(DataMapper $sqlReader)
77
    {
78
        $this->sqlReader = $sqlReader;
79
    }
80
81
    /**
82
     * @param ConfigurationManager $configurationManager
83
     */
84
    public function injectConfigurationManager(ConfigurationManager $configurationManager)
85
    {
86
        $this->configurationManager = $configurationManager;
87
    }
88
89
    public function __construct()
90
    {
91
92
    }
93
94
    /**
95
     * Collect information about relevant tables from `ext_tables.sql` and the
96
     * Extbase classmap.
97
     */
98
    public function collectTables(): array
99
    {
100
        $sqlCode = $this->sqlReader->getTablesDefinitionString(true);
101
        $createTableStatements = $this->sqlReader->getCreateTableStatementArray($sqlCode);
102
103
        $tableToClassName = $this->getTableClassMap();
104
105
        $result = [];
106
107
        foreach ($createTableStatements as $statement) {
108
            $parser = new Parser($statement);
109
            list($table) = $parser->parse();
110
111
            $tableName = $table->getName();
112
            if (!str_starts_with($tableName, 'tx_dlf_')) {
113
                continue;
114
            }
115
116
            $className = $tableToClassName[$tableName] ?? null;
117
118
            $result[] = $this->getTableInfo($table, $className);
119
        }
120
121
        return $result;
122
    }
123
124
    /**
125
     * Get a map from database table names to their domain model class names.
126
     */
127
    public function getTableClassMap(): array
128
    {
129
        $frameworkConfiguration = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
130
131
        $result = [];
132
133
        foreach ($frameworkConfiguration['persistence']['classes'] as $className => $tableConf) {
134
            $tableName = $tableConf['mapping']['tableName'];
135
            $result[$tableName] = $className;
136
        }
137
138
        return $result;
139
    }
140
141
    /**
142
     * Collect information about a single table.
143
     *
144
     * @param Table $table The table to be analyzed
145
     * @param string|null $className Fully qualified name of the domain model class
146
     */
147
    protected function getTableInfo(Table $table, ?string $className): object
148
    {
149
        $tableName = $table->getName();
150
151
        $isPrimary = [];
152
        if (!is_null($primaryKey = $table->getPrimaryKey())) {
153
            foreach ($primaryKey->getUnquotedColumns() as $primaryColumn) {
154
                $isPrimary[$primaryColumn] = true;
155
            }
156
        }
157
158
        $columns = [];
159
        foreach ($table->getColumns() as $column) {
160
            $columnName = $column->getName();
161
162
            $columns[$columnName] = (object) [
163
                'name' => $columnName,
164
                'type' => $column->getType(),
165
                'isPrimary' => isset($isPrimary[$columnName]),
166
                'sqlComment' => $column->getComment() ?? '',
167
                'fieldComment' => '',
168
                'feComment' => $this->languageService->sL($GLOBALS['TCA'][$tableName]['columns'][$columnName]['label'] ?? ''),
169
            ];
170
        }
171
172
        $result = (object) [
173
            'name' => $tableName,
174
            'columns' => $columns,
175
            'modelClass' => null,
176
            'sqlComment' => $table->getComment() ?? '',
177
            'classComment' => '',
178
            'feComment' => $this->languageService->sL($GLOBALS['TCA'][$tableName]['ctrl']['title'] ?? ''),
179
        ];
180
181
        // Integrate doc-comments from model class and its fields
182
        if ($className !== null) {
183
            $reflection = new ReflectionClass($className);
184
185
            $dataMap = $this->dataMapper->getDataMap($className);
186
187
            foreach ($reflection->getProperties() as $property) {
188
                // If the TCA doesn't list the column, DataMap won't know about it.
189
                // In that case, try to guess the column name from the property name.
190
191
                $column = $dataMap->getColumnMap($property->getName());
192
                $columnName = $column === null
193
                    ? GeneralUtility::camelCaseToLowerCaseUnderscored($property->getName())
194
                    : $column->getColumnName();
195
196
                if (isset($result->columns[$columnName])) {
197
                    $result->columns[$columnName]->fieldComment = $this->parseDocComment($property->getDocComment());
198
                }
199
            }
200
201
            $result->modelClass = $className;
202
            $result->classComment = $this->parseDocComment($reflection->getDocComment());
203
        }
204
205
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result could return the type object which is incompatible with the type-hinted return object. Consider adding an additional type-check to rule them out.
Loading history...
206
    }
207
208
    protected function parseDocComment($docComment)
209
    {
210
        // TODO: Consider using phpDocumentor (though that splits the docblock into summary and description)
211
212
        // Adopted from DocCommentParser in TYPO3 v9
213
        // https://github.com/TYPO3/typo3/blob/57944c8c5add00f0e8a1a5e1d07f30a8f20a8201/typo3/sysext/extbase/Classes/Reflection/DocCommentParser.php
214
        $text = '';
215
        $lines = explode("\n", $docComment);
216
        foreach ($lines as $line) {
217
            // Stop parsing at first tag
218
            if ($line !== '' && strpos($line, '@') !== false) {
219
                break;
220
            }
221
222
            // There may be a single non-signifying space after the doc-comment asterisk,
223
            // which is not included.
224
            $text .= preg_replace('#\\s*/?[*/]*\\s?(.*)$#', '$1', $line) . "\n";
225
        }
226
        $text = trim($text);
227
228
        return $text;
229
    }
230
231
    /**
232
     * Transform table structure into .rst page.
233
     */
234
    public function generatePage(array $tables)
235
    {
236
        $page = new RstSection();
237
        $page->setHeader('Database Tables');
238
        $page->addText(<<<RST
239
This is a reference of all database tables defined by Kitodo.Presentation.
240
241
.. 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 ``composer docs:db`` inside the Kitodo.Presentation base folder.
242
RST);
243
244
        // Sort tables alphabetically
245
        usort($tables, function ($lhs, $rhs) {
246
            return $lhs->name <=> $rhs->name;
247
        });
248
249
        foreach ($tables as $tableInfo) {
250
            $section = $page->subsection();
251
252
            // Set header
253
            $header = $tableInfo->name;
254
            if (!empty($tableInfo->feComment)) {
255
                $header .= ': ' . $tableInfo->feComment;
256
            }
257
            $section->setHeader($header);
258
259
            // Set introductory text of subsection
260
            if ($tableInfo->modelClass) {
261
                $section->addText('Extbase domain model: ``' . $tableInfo->modelClass . '``');
262
            }
263
            $section->addText($tableInfo->classComment);
264
            $section->addText($tableInfo->sqlComment);
265
266
            // Generate main table
267
            $header = [[
268
                'field' => 'Field',
269
                'description' => 'Description',
270
            ]];
271
272
            $rows = array_map(function ($column) use ($page) {
273
                return [
274
                    'field' => (
275
                        $page->format($column->name, ['bold' => $column->isPrimary])
276
                        . "\u{00a0}\u{00a0}"
277
                        . $page->format($column->type->getName(), ['italic' => true])
278
                    ),
279
280
                    'description' => $page->paragraphs([
281
                        $page->format($column->feComment, ['italic' => true]),
282
                        $column->fieldComment,
283
                        $column->sqlComment,
284
                    ]),
285
                ];
286
            }, $tableInfo->columns);
287
288
            $section->addTable($rows, $header);
289
        }
290
        return $page;
291
    }
292
}
293