StructureGenerator   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 278
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 19
c 0
b 0
f 0
lcom 1
cbo 5
dl 0
loc 278
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A generate() 0 40 2
A formatAddFields() 0 22 4
A formatFieldsComment() 0 14 4
A createPhpDocBlockFromText() 0 10 1
A checkRelationInformation() 0 20 3
A getFieldInformation() 0 18 2
A getPrimaryKey() 0 9 1
A getTableComment() 0 9 1
A getCodeTemplate() 0 45 1
1
<?php
2
/*
3
 * This file is part of Pomm's ModelManager package.
4
 *
5
 * (c) 2014 - 2015 Grégoire HUBERT <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace PommProject\ModelManager\Generator;
11
12
use PommProject\Foundation\ConvertedResultIterator;
13
use PommProject\Foundation\Inflector;
14
use PommProject\Foundation\ParameterHolder;
15
use PommProject\ModelManager\Exception\GeneratorException;
16
17
/**
18
 * StructureGenerator
19
 *
20
 * Generate a RowStructure file from relation inspection.
21
 *
22
 * @package   ModelManager
23
 * @copyright 2014 - 2015 Grégoire HUBERT
24
 * @author    Grégoire HUBERT
25
 * @license   X11 {@link http://opensource.org/licenses/mit-license.php}
26
 */
27
class StructureGenerator extends BaseGenerator
28
{
29
    /**
30
     * generate
31
     *
32
     * Generate structure file.
33
     *
34
     * @see BaseGenerator
35
     */
36
    public function generate(ParameterHolder $input, array $output = [])
37
    {
38
        $table_oid          = $this->checkRelationInformation();
39
        $field_information = $this->getFieldInformation($table_oid);
40
        $primary_key        = $this->getPrimaryKey($table_oid);
41
        $table_comment      = $this->getTableComment($table_oid);
42
43
        if ($table_comment === null) {
44
            $table_comment = <<<TEXT
45
46
Class and fields comments are inspected from table and fields comments. Just add comments in your database and they will appear here.
47
@see http://www.postgresql.org/docs/9.0/static/sql-comment.html
48
TEXT;
49
        }
50
51
        $this
52
            ->outputFileCreation($output)
53
            ->saveFile(
54
                $this->filename,
55
                $this->mergeTemplate(
56
                    [
57
                        'namespace'      => $this->namespace,
58
                        'class_name'     => $input->getParameter('class_name', Inflector::studlyCaps($this->relation)),
59
                        'relation'       => sprintf("%s.%s", $this->schema, $this->relation),
60
                        'primary_key'    => join(
61
                            ', ',
62
                            array_map(
63
                                function ($val) { return sprintf("'%s'", $val); },
64
                                $primary_key
65
                            )
66
                        ),
67
                        'add_fields'     => $this->formatAddFields($field_information),
68
                        'table_comment'  => $this->createPhpDocBlockFromText($table_comment),
69
                        'fields_comment' => $this->formatFieldsComment($field_information),
70
                    ]
71
                )
72
            );
73
74
        return $output;
75
    }
76
77
    /**
78
     * formatAddFields
79
     *
80
     * Format 'addField' method calls.
81
     *
82
     * @access protected
83
     * @param  ConvertedResultIterator $field_information
84
     * @return string
85
     */
86
    protected function formatAddFields(ConvertedResultIterator $field_information)
87
    {
88
        $strings = [];
89
90
        foreach ($field_information as $info) {
91
            if (preg_match('/^(?:(.*)\.)?_(.*)$/', $info['type'], $matches)) {
92
                if ($matches[1] !== '') {
93
                    $info['type'] = sprintf("%s.%s[]", $matches[1], $matches[2]);
94
                } else {
95
                    $info['type'] = $matches[2].'[]';
96
                }
97
            }
98
99
            $strings[] = sprintf(
100
                "            ->addField('%s', '%s')",
101
                $info['name'],
102
                $info['type']
103
            );
104
        }
105
106
        return join("\n", $strings);
107
    }
108
109
    /**
110
     * formatFieldsComment
111
     *
112
     * Format fields comment to be in the class comment. This is because there
113
     * can be very long comments or comments with carriage returns. It is
114
     * furthermore more convenient to get all the descriptions in the head of
115
     * the generated class.
116
     *
117
     * @access protected
118
     * @param  ConvertedResultIterator $field_information
119
     * @return string
120
     */
121
    protected function formatFieldsComment(ConvertedResultIterator $field_information)
122
    {
123
        $comments = [];
124
        foreach ($field_information as $info) {
125
            if ($info['comment'] === null) {
126
                continue;
127
            }
128
129
            $comments[] = sprintf(" * %s:", $info['name']);
130
            $comments[] = $this->createPhpDocBlockFromText($info['comment']);
131
        }
132
133
        return count($comments) > 0 ? join("\n", $comments) : ' *';
134
    }
135
136
    /**
137
     * createPhpDocBlockFromText
138
     *
139
     * Format a text into a PHPDoc comment block.
140
     *
141
     * @access protected
142
     * @param  string $text
143
     * @return string
144
     */
145
    protected function createPhpDocBlockFromText($text)
146
    {
147
        return join(
148
            "\n",
149
            array_map(
150
                function ($line) { return ' * '.$line; },
151
                explode("\n", wordwrap($text))
152
            )
153
        );
154
    }
155
156
    /**
157
     * checkRelationInformation
158
     *
159
     * Check if the given schema and relation exist. If so, the table oid is
160
     * returned, otherwise a GeneratorException is thrown.
161
     *
162
     * @access private
163
     * @throws GeneratorException
164
     * @return int $oid
165
     */
166
    private function checkRelationInformation()
167
    {
168
        if ($this->getInspector()->getSchemaOid($this->schema) === null) {
169
            throw new GeneratorException(sprintf("Schema '%s' not found.", $this->schema));
170
        }
171
172
        $table_oid = $this->getInspector()->getTableOid($this->schema, $this->relation);
173
174
        if ($table_oid === null) {
175
            throw new GeneratorException(
176
                sprintf(
177
                    "Relation '%s' could not be found in schema '%s'.",
178
                    $this->relation,
179
                    $this->schema
180
                )
181
            );
182
        }
183
184
        return $table_oid;
185
    }
186
187
    /**
188
     * getFieldInformation
189
     *
190
     * Fetch a table field information.
191
     *
192
     * @access protected
193
     * @param  int   $table_oid
194
     * @throws GeneratorException
195
     * @return ConvertedResultIterator $fields_info
196
     */
197
    protected function getFieldInformation($table_oid)
198
    {
199
        $fields_info = $this
200
            ->getInspector()
201
            ->getTableFieldInformation($table_oid)
202
            ;
203
204
        if ($fields_info === null) {
205
            throw new GeneratorException(
206
                sprintf(
207
                    "Error while fetching fields information for table oid '%s'.",
208
                    $table_oid
209
                )
210
            );
211
        }
212
213
        return $fields_info;
214
    }
215
216
    /**
217
     * getPrimaryKey
218
     *
219
     * Return the primary key of a relation if any.
220
     *
221
     * @access protected
222
     * @param  string $table_oid
223
     * @return array  $primary_key
224
     */
225
    protected function getPrimaryKey($table_oid)
226
    {
227
        $primary_key = $this
228
            ->getInspector()
229
            ->getPrimaryKey($table_oid)
230
            ;
231
232
        return $primary_key;
233
    }
234
235
    /**
236
     * getTableComment
237
     *
238
     * Grab table comment from database.
239
     *
240
     * @access protected
241
     * @param  int         $table_oid
242
     * @return string|null
243
     */
244
    protected function getTableComment($table_oid)
245
    {
246
        $comment = $this
247
            ->getInspector()
248
            ->getTableComment($table_oid)
249
            ;
250
251
        return $comment;
252
    }
253
254
    /**
255
     * getCodeTemplate
256
     *
257
     * @see BaseGenerator
258
     */
259
    protected function getCodeTemplate()
260
    {
261
        return <<<'_'
262
<?php
263
/**
264
 * This file has been automatically generated by Pomm's generator.
265
 * You MIGHT NOT edit this file as your changes will be lost at next
266
 * generation.
267
 */
268
269
namespace {:namespace:};
270
271
use PommProject\ModelManager\Model\RowStructure;
272
273
/**
274
 * {:class_name:}
275
 *
276
 * Structure class for relation {:relation:}.
277
{:table_comment:}
278
 *
279
{:fields_comment:}
280
 *
281
 * @see RowStructure
282
 */
283
class {:class_name:} extends RowStructure
284
{
285
    /**
286
     * __construct
287
     *
288
     * Structure definition.
289
     *
290
     * @access public
291
     */
292
    public function __construct()
293
    {
294
        $this
295
            ->setRelation('{:relation:}')
296
            ->setPrimaryKey([{:primary_key:}])
297
{:add_fields:}
298
            ;
299
    }
300
}
301
302
_;
303
    }
304
}
305