Completed
Push — master ( 1f4906...cc7288 )
by Vitaly
05:59
created

Generator   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 556
Duplicated Lines 5.04 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 36
Bugs 8 Features 17
Metric Value
wmc 30
c 36
b 8
f 17
lcom 1
cbo 3
dl 28
loc 556
rs 10

19 Methods

Rating   Name   Duplication   Size   Complexity  
A entityName() 0 4 1
A getValidName() 0 4 1
A fullEntityName() 0 4 1
A fieldName() 0 4 1
A additionalFieldType() 0 4 1
A transliterated() 0 51 1
A constantNameByValue() 0 11 2
A generateFieldConditionMethod() 14 14 1
A generateLocalizedFieldConditionMethod() 14 14 1
A createEntityClass() 0 58 3
A generateTableFieldMethod() 0 12 1
B createTableRowClass() 0 30 2
A createTableClass() 0 47 2
A createQueryClass() 0 65 3
A entityHash() 0 9 1
A entityNavigations() 0 7 1
A navigationFields() 0 12 3
A createEntityClasses() 0 55 3
A __construct() 0 5 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
//[PHPCOMPRESSOR(remove,start)]
3
/**
4
 * Created by PhpStorm.
5
 * User: VITALYIEGOROV
6
 * Date: 09.12.15
7
 * Time: 14:34
8
 */
9
namespace samsoncms\api;
10
11
use samson\activerecord\dbMySQLConnector;
12
use samson\cms\CMSMaterial;
13
use samsoncms\api\query\Generic;
14
use samsonframework\orm\DatabaseInterface;
15
16
/**
17
 * Entity classes generator.
18
 * @package samsoncms\api
19
 */
20
class Generator
21
{
22
    /** @var DatabaseInterface */
23
    protected $database;
24
25
    /** @var \samsonphp\generator\Generator */
26
    protected $generator;
27
28
    /**
29
     * Transliterate string to english.
30
     *
31
     * @param string $string Source string
32
     * @return string Transliterated string
33
     */
34
    protected function transliterated($string)
35
    {
36
        return str_replace(
37
            ' ',
38
            '',
39
            ucwords(iconv("UTF-8", "UTF-8//IGNORE", strtr($string, array(
40
                            "'" => "",
41
                            "`" => "",
42
                            "-" => " ",
43
                            "_" => " ",
44
                            "а" => "a", "А" => "a",
45
                            "б" => "b", "Б" => "b",
46
                            "в" => "v", "В" => "v",
47
                            "г" => "g", "Г" => "g",
48
                            "д" => "d", "Д" => "d",
49
                            "е" => "e", "Е" => "e",
50
                            "ж" => "zh", "Ж" => "zh",
51
                            "з" => "z", "З" => "z",
52
                            "и" => "i", "И" => "i",
53
                            "й" => "y", "Й" => "y",
54
                            "к" => "k", "К" => "k",
55
                            "л" => "l", "Л" => "l",
56
                            "м" => "m", "М" => "m",
57
                            "н" => "n", "Н" => "n",
58
                            "о" => "o", "О" => "o",
59
                            "п" => "p", "П" => "p",
60
                            "р" => "r", "Р" => "r",
61
                            "с" => "s", "С" => "s",
62
                            "т" => "t", "Т" => "t",
63
                            "у" => "u", "У" => "u",
64
                            "ф" => "f", "Ф" => "f",
65
                            "х" => "h", "Х" => "h",
66
                            "ц" => "c", "Ц" => "c",
67
                            "ч" => "ch", "Ч" => "ch",
68
                            "ш" => "sh", "Ш" => "sh",
69
                            "щ" => "sch", "Щ" => "sch",
70
                            "ъ" => "", "Ъ" => "",
71
                            "ы" => "y", "Ы" => "y",
72
                            "ь" => "", "Ь" => "",
73
                            "э" => "e", "Э" => "e",
74
                            "ю" => "yu", "Ю" => "yu",
75
                            "я" => "ya", "Я" => "ya",
76
                            "і" => "i", "І" => "i",
77
                            "ї" => "yi", "Ї" => "yi",
78
                            "є" => "e", "Є" => "e"
79
                        )
80
                    )
81
                )
82
            )
83
        );
84
    }
85
86
    /**
87
     * Get class constant name by its value.
88
     *
89
     * @param string $value Constant value
90
     * @param string $className Class name
91
     * @return string Full constant name
92
     */
93
    protected function constantNameByValue($value, $className = Field::ENTITY)
94
    {
95
        // Get array where class constants are values and their values are keys
96
        $nameByValue = array_flip((new \ReflectionClass($className))->getConstants());
97
98
        // Try to find constant by its value
99
        if (isset($nameByValue[$value])) {
100
            // Return constant name
101
            return $nameByValue[$value];
102
        }
103
    }
104
105
    /**
106
     * Get correct entity name.
107
     *
108
     * @param string $navigationName Original navigation entity name
109
     * @return string Correct PHP-supported entity name
110
     */
111
    protected function entityName($navigationName)
112
    {
113
        return ucfirst($this->getValidName($this->transliterated($navigationName)));
114
    }
115
	
116
    /**
117
     * Remove all wrong characters from entity name
118
     *
119
     * @param string $navigationName Original navigation entity name
120
     * @return string Correct PHP-supported entity name
121
     */
122
    protected function getValidName($navigationName)
123
    {
124
        return preg_replace('/(^\d*)|([^\w\d_])/', '', $navigationName);
125
    }
126
127
    /**
128
     * Get correct full entity name with name space.
129
     *
130
     * @param string $navigationName Original navigation entity name
131
     * @param string $namespace Namespace
132
     * @return string Correct PHP-supported entity name
133
     */
134
    protected function fullEntityName($navigationName, $namespace = __NAMESPACE__)
135
    {
136
        return str_replace('\\', '\\\\' , '\\'.$namespace.'\\'.$this->entityName($navigationName));
0 ignored issues
show
Coding Style introduced by
Space found before comma in function call
Loading history...
137
    }
138
139
    /**
140
     * Get correct field name.
141
     *
142
     * @param string $fieldName Original field name
143
     * @return string Correct PHP-supported field name
144
     */
145
    protected function fieldName($fieldName)
146
    {
147
        return $fieldName = lcfirst($this->transliterated($fieldName));
0 ignored issues
show
Unused Code introduced by
$fieldName is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
148
    }
149
150
    /**
151
     * Get additional field type in form of Field constant name
152
     * by database additional field type identifier.
153
     *
154
     * @param integer $fieldType Additional field type identifier
155
     * @return string Additional field type constant
156
     */
157
    protected function additionalFieldType($fieldType)
158
    {
159
        return 'Field::'.$this->constantNameByValue($fieldType);
160
    }
161
162
    /**
163
     * Generate Query::where() analog for specific field.
164
     *
165
     * @param string $fieldName Field name
166
     * @param string $fieldId Field primary identifier
167
     * @param string $fieldType Field PHP type
168
     * @return string Generated PHP method code
169
     */
170 View Code Duplication
    protected function generateFieldConditionMethod($fieldName, $fieldId, $fieldType)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
171
    {
172
        $code = "\n\t" . '/**';
173
        $code .= "\n\t" . ' * Add '.$fieldName.'(#' . $fieldId . ') field query condition.';
174
        $code .= "\n\t" . ' * @param '.Field::phpType($fieldType).' $value Field value';
175
        $code .= "\n\t" . ' * @return self Chaining';
176
        $code .= "\n\t" . ' * @see Generic::where()';
177
        $code .= "\n\t" . ' */';
178
        $code .= "\n\t" . 'public function ' . $fieldName . '($value)';
179
        $code .= "\n\t" . "{";
180
        $code .= "\n\t\t" . 'return $this->where("'.$fieldName.'", $value);';
181
182
        return $code . "\n\t" . "}"."\n";
183
    }
184
185
    /**
186
     * Generate Query::where() analog for specific field.
187
     *
188
     * @param string $fieldName Field name
189
     * @param string $fieldId Field primary identifier
190
     * @param string $fieldType Field PHP type
191
     * @return string Generated PHP method code
192
     */
193 View Code Duplication
    protected function generateLocalizedFieldConditionMethod($fieldName, $fieldId, $fieldType)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
194
    {
195
        $code = "\n\t" . '/**';
196
        $code .= "\n\t" . ' * Add '.$fieldName.'(#' . $fieldId . ') field query condition.';
197
        $code .= "\n\t" . ' * @param '.Field::phpType($fieldType).' $value Field value';
198
        $code .= "\n\t" . ' * @return self Chaining';
199
        $code .= "\n\t" . ' * @see Generic::where()';
200
        $code .= "\n\t" . ' */';
201
        $code .= "\n\t" . 'public function ' . $fieldName . '($value)';
202
        $code .= "\n\t" . "{";
203
        $code .= "\n\t\t" . 'return $this->where("'.$fieldName.'", $value);';
204
205
        return $code . "\n\t" . "}"."\n";
206
    }
207
208
    /**
209
     * Create entity PHP class code.
210
     *
211
     * @param string $navigationName Original entity name
212
     * @param string $entityName PHP entity name
213
     * @param array $navigationFields Collection of entity additional fields
214
     * @return string Generated entity query PHP class code
215
     */
216
    protected function createEntityClass($navigationName, $entityName, $navigationFields)
217
    {
218
        $this->generator
219
            ->multicomment(array('"'.$navigationName.'" entity class'))
220
            ->defClass($entityName, 'Entity')
221
            ->commentVar('string', 'Entity full class name')
222
            ->defClassConst('ENTITY', $this->fullEntityName($entityName))
223
            ->commentVar('string', 'Entity manager full class name')
224
            ->defClassConst('MANAGER', $this->fullEntityName($entityName.'Query'))
225
            ->commentVar('string', 'Not transliterated entity name')
226
            ->defClassVar('$viewName', 'protected static');
227
228
        // Get old AR collections of metadata
229
        $select = \samson\activerecord\material::$_sql_select;
230
        $attributes = \samson\activerecord\material::$_attributes;
231
        $map = \samson\activerecord\material::$_map;
232
        $from = \samson\activerecord\material::$_sql_from;
233
        $group = \samson\activerecord\material::$_own_group;
234
        $relationAlias = \samson\activerecord\material::$_relation_alias;
235
        $relationType = \samson\activerecord\material::$_relation_type;
236
        $relations = \samson\activerecord\material::$_relations;
237
238
239
        // Add SamsonCMS material needed data
240
        $select['this'] = ' STRAIGHT_JOIN ' . $select['this'];
241
        $from['this'] .= "\n" . 'LEFT JOIN ' . dbMySQLConnector::$prefix . 'materialfield as _mf on ' . dbMySQLConnector::$prefix . 'material.MaterialID = _mf.MaterialID';
242
        $group[] = dbMySQLConnector::$prefix . 'material.MaterialID';
243
244
        foreach ($navigationFields as $fieldID => $fieldRow) {
245
            $fieldName = $this->fieldName($fieldRow['Name']);
246
247
            $attributes[$fieldName] = $fieldName;
248
            $map[$fieldName] = dbMySQLConnector::$prefix . 'material.' . $fieldName;
249
250
            $equal = '((_mf.FieldID = ' . $fieldID . ')&&(_mf.locale ' . ($fieldRow['local'] ? ' = "@locale"' : 'IS NULL') . '))';
251
252
            // Save additional field
253
            $select['this'] .= "\n\t\t" . ',MAX(IF(' . $equal . ', _mf.`' . Field::valueColumn($fieldRow['Type']) . '`, NULL)) as `' . $fieldName . '`';
254
255
            $this->generator
256
                ->commentVar('string', $fieldRow['Description'] . ' Field #' . $fieldID . ' variable name')
257
                ->defClassConst('F_' . $fieldName, $fieldName)
258
                ->commentVar(Field::phpType($fieldRow['Type']), $fieldRow['Description'] . ' Field #' . $fieldID)
259
                ->defClassVar('$' . $fieldName, 'public');
260
        }
261
262
        return $this->generator
263
            ->defClassVar('$_sql_select', 'public static ', $select)
0 ignored issues
show
Documentation introduced by
$select is of type array<string,string,{"this":"string"}>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
264
            ->defClassVar('$_attributes', 'public static ', $attributes)
0 ignored issues
show
Documentation introduced by
$attributes is of type array, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
265
            ->defClassVar('$_map', 'public static ', $map)
0 ignored issues
show
Documentation introduced by
$map is of type array, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
266
            ->defClassVar('$_sql_from', 'public static ', $from)
0 ignored issues
show
Documentation introduced by
$from is of type array<string,string,{"this":"string"}>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
267
            ->defClassVar('$_own_group', 'public static ', $group)
0 ignored issues
show
Documentation introduced by
$group is of type array<integer,string>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
268
            ->defClassVar('$_relation_alias', 'public static ', $relationAlias)
0 ignored issues
show
Documentation introduced by
$relationAlias is of type array, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
269
            ->defClassVar('$_relation_type', 'public static ', $relationType)
0 ignored issues
show
Documentation introduced by
$relationType is of type array, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
270
            ->defClassVar('$_relations', 'public static ', $relations)
0 ignored issues
show
Documentation introduced by
$relations is of type array, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
271
            ->endclass()
272
            ->flush();
273
    }
274
275
    /**
276
     * Generate FieldsTable::values() analog for specific field.
277
     *
278
     * @param string $fieldName Field name
279
     * @param string $fieldId Field primary identifier
280
     * @param string $fieldType Field PHP type
281
     * @return string Generated PHP method code
282
     */
283
    protected function generateTableFieldMethod($fieldName, $fieldId, $fieldType)
284
    {
285
        $code = "\n\t" . '/**';
286
        $code .= "\n\t" . ' * Get table column '.$fieldName.'(#' . $fieldId . ') values.';
287
        $code .= "\n\t" . ' * @return array Collection('.Field::phpType($fieldType).') of table column values';
288
        $code .= "\n\t" . ' */';
289
        $code .= "\n\t" . 'public function ' . $fieldName . '()';
290
        $code .= "\n\t" . "{";
291
        $code .= "\n\t\t" . 'return $this->values('.$fieldId.');';
292
293
        return $code . "\n\t" . "}"."\n";
294
    }
295
296
    /**
297
     * Create fields table row PHP class code.
298
     *
299
     * @param string $navigationName Original entity name
300
     * @param string $entityName PHP entity name
301
     * @param array $navigationFields Collection of entity additional fields
302
     * @return string Generated entity query PHP class code
303
     */
304
    protected function createTableRowClass($navigationName, $entityName, $navigationFields)
305
    {
306
        $class = "\n";
307
        $class .= "\n" . '/**';
308
        $class .= "\n" . ' * Class for getting "'.$navigationName.'" fields table rows';
309
        $class .= "\n" . ' */';
310
        $class .= "\n" . 'class ' . $entityName . ' extends Row';
311
        $class .= "\n" . '{';
312
313
        // Iterate additional fields
314
        $constants = '';
315
        $variables = '';
316
        foreach ($navigationFields as $fieldID => $fieldRow) {
317
            $fieldName = $this->fieldName($fieldRow['Name']);
318
319
            $constants .= "\n\t" . '/** ' . Field::phpType($fieldRow['Type']) . ' '.$fieldRow['Description'].' Field #' . $fieldID . ' variable name */';
320
            // Store original field name
321
            $constants .= "\n\t" . 'const F_' . strtoupper($fieldName) . ' = "'.$fieldName.'";';
322
323
            $variables .= "\n\t" . '/** ' . Field::phpType($fieldRow['Type']) . ' '.$fieldRow['Description'].' Field #' . $fieldID . ' row value */';
324
            $variables .= "\n\t" . 'public $' . $fieldName . ';';
325
        }
326
327
        $class .= $constants;
328
        $class .= "\n\t";
329
        $class .= $variables;
330
        $class .= "\n" . '}';
331
332
        return $class;
333
    }
334
335
    /**
336
     * Create fields table PHP class code.
337
     *
338
     * @param integer $navigationID     Entity navigation identifier
339
     * @param string  $navigationName   Original entity name
340
     * @param string  $entityName       PHP entity name
341
     * @param array   $navigationFields Collection of entity additional fields
342
     * @param string  $rowClassName Row class name
343
     *
344
     * @return string Generated entity query PHP class code
345
     * @throws exception\AdditionalFieldTypeNotFound
346
     */
347
    protected function createTableClass($navigationID, $navigationName, $entityName, $navigationFields, $rowClassName)
348
    {
349
        $this->generator
350
            ->multiComment(array('Class for getting "'.$navigationName.'" fields table'))
351
            ->defClass($entityName, 'FieldsTable');
352
353
        // Iterate additional fields
354
        $fields = array();
355
        foreach ($navigationFields as $fieldID => $fieldRow) {
356
            $fieldName = $this->fieldName($fieldRow['Name']);
357
358
            $this->generator
359
                ->text($this->generateTableFieldMethod(
360
                    $fieldName,
361
                    $fieldRow[Field::F_PRIMARY],
362
                    $fieldRow[Field::F_TYPE]
363
                ))
364
                ->commentVar(Field::phpType($fieldRow['Type']), $fieldRow['Description'] . ' Field #' . $fieldID . ' variable name')
365
                ->defClassConst('F_' . $fieldName, $fieldName);
366
367
            // Collection original to new one field names
368
            $fields[$fieldRow['Name']] = $fieldName;
369
        }
370
371
        $class = "\n\t".'/**';
372
        $class .= "\n\t".' * @param QueryInterface $query Database query instance';
373
        $class .= "\n\t".' * @param ViewInterface $renderer Rendering instance';
374
        $class .= "\n\t".' * @param integer $entityID Entity identifier to whom this table belongs';
375
        $class .= "\n\t".' * @param string $locale Localization identifier';
376
        $class .= "\n\t".' */';
377
        $class .= "\n\t".'public function __construct(QueryInterface $query, ViewInterface $renderer, $entityID, $locale = null)';
378
        $class .= "\n\t".'{';
379
        $class .= "\n\t\t".'parent::__construct($query, $renderer, static::$navigationIDs, $entityID, $locale);';
380
        $class .= "\n\t".'}'."\n";
381
382
        $this->generator->text($class);
383
384
        return $this->generator
385
            ->commentVar('array', 'Collection of real additional field names')
386
            ->defClassVar('$fieldsRealNames', 'public static', $fields)
0 ignored issues
show
Documentation introduced by
$fields is of type array, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
387
            ->commentVar('array', 'Collection of navigation identifiers')
388
            ->defClassVar('$navigationIDs', 'protected static', array($navigationID))
0 ignored issues
show
Documentation introduced by
array($navigationID) is of type array<integer,integer,{"0":"integer"}>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
389
            ->commentVar('string', 'Row class name')
390
            ->defClassVar('$identifier', 'protected', $this->fullEntityName($rowClassName))
391
            ->endClass()
392
            ->flush();
393
    }
394
395
    /**
396
     * Create entity query PHP class code.
397
     *
398
     * @param integer $navigationID Entity navigation identifier
399
     * @param string $navigationName Original entity name
400
     * @param string $entityName PHP entity name
401
     * @param array $navigationFields Collection of entity additional fields
402
     * @return string Generated entity query PHP class code
403
     */
404
    protected function createQueryClass($navigationID, $navigationName, $entityName, $navigationFields)
405
    {
406
        $this->generator->multicomment(array(
407
            'Class for getting "'.$navigationName.'" instances from database',
408
            '@method '.$this->entityName($navigationName).'[] find() Get entities collection',
409
            '@method '.$this->entityName($navigationName).' first() Get entity',
410
            '@method '.$entityName.' where($fieldName, $fieldValue = null, $fieldRelation = ArgumentInterface::EQUAL)',
411
            '@method '.$entityName.' primary($value) Query for chaining',
412
            '@method '.$entityName.' identifier($value) Query for chaining',
413
            '@method '.$entityName.' created($value) Query for chaining',
414
            '@method '.$entityName.' modified($value) Query for chaining',
415
            '@method '.$entityName.' published($value) Query for chaining'
416
        ))->defClass($entityName, '\samsoncms\api\query\Entity')
417
        ;
418
419
        // Iterate additional fields
420
        $localizedFieldIDs = array();
421
        $notLocalizedFieldIDs = array();
422
        $allFieldIDs = array();
423
        $allFieldNames = array();
424
        $allFieldValueColumns = array();
425
        $realNames = array();
426
        foreach ($navigationFields as $fieldID => $fieldRow) {
427
            $fieldName = $this->fieldName($fieldRow['Name']);
428
429
            // TODO: Add different method generation depending on their field type
430
            $this->generator->text($this->generateFieldConditionMethod(
431
                $fieldName,
432
                $fieldRow[Field::F_PRIMARY],
433
                $fieldRow[Field::F_TYPE]
434
            ));
435
436
            // Store field metadata
437
            $realNames[$fieldRow['Name']] = $fieldName;
438
            $allFieldIDs[$fieldID] = $fieldName;
439
            $allFieldNames[$fieldName] = $fieldID;
440
            $allFieldValueColumns[$fieldID] = Field::valueColumn($fieldRow[Field::F_TYPE]);
441
            if ($fieldRow[Field::F_LOCALIZED] == 1) {
442
                $localizedFieldIDs[$fieldID] = $fieldName;
443
            } else {
444
                $notLocalizedFieldIDs[$fieldID] = $fieldName;
445
            }
446
        }
447
448
        return $this->generator
449
            ->commentVar('array', 'Collection of real additional field names')
450
            ->defClassVar('$fieldRealNames', 'public static', $realNames)
0 ignored issues
show
Documentation introduced by
$realNames is of type array, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
451
            ->commentVar('array', 'Collection of navigation identifiers')
452
            ->defClassVar('$navigationIDs', 'protected static', array($navigationID))
0 ignored issues
show
Documentation introduced by
array($navigationID) is of type array<integer,integer,{"0":"integer"}>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
453
            ->commentVar('string', 'Not transliterated entity name')
454
            ->defClassVar('$identifier', 'protected static', $this->fullEntityName($navigationName))
455
            ->commentVar('array', 'Collection of localized additional fields identifiers')
456
            ->defClassVar('$localizedFieldIDs', 'protected static', $localizedFieldIDs)
0 ignored issues
show
Documentation introduced by
$localizedFieldIDs is of type array, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
457
            ->commentVar('array', 'Collection of NOT localized additional fields identifiers')
458
            ->defClassVar('$notLocalizedFieldIDs', 'protected static', $notLocalizedFieldIDs)
0 ignored issues
show
Documentation introduced by
$notLocalizedFieldIDs is of type array, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
459
            ->commentVar('array', 'Collection of localized additional fields identifiers')
460
            ->defClassVar('$fieldIDs', 'protected static', $allFieldIDs)
0 ignored issues
show
Documentation introduced by
$allFieldIDs is of type array, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
461
            ->commentVar('array', 'Collection of additional fields value column names')
462
            ->defClassVar('$fieldValueColumns', 'protected static', $allFieldValueColumns)
0 ignored issues
show
Documentation introduced by
$allFieldValueColumns is of type array, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
463
            ->commentVar('array', 'Collection of additional field names')
464
            ->defClassVar('$fieldNames', 'public static', $allFieldNames)
0 ignored issues
show
Documentation introduced by
$allFieldNames is of type array, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
465
            ->endClass()
466
            ->flush()
467
        ;
468
    }
469
470
    /** @return string Entity state hash */
471
    public function entityHash()
472
    {
473
        // Получим информацию о всех таблицах из БД
474
        return md5(serialize($this->database->fetch(
475
            'SELECT `TABLES`.`TABLE_NAME` as `TABLE_NAME`
476
              FROM `information_schema`.`TABLES` as `TABLES`
477
              WHERE `TABLES`.`TABLE_SCHEMA`="' . $this->database->database() . '";'
478
        )));
479
    }
480
481
    /** @return array Get collection of navigation objects */
482
    protected function entityNavigations($type = 0)
483
    {
484
        return $this->database->fetch('
485
        SELECT * FROM `structure`
486
        WHERE `Active` = "1" AND `Type` = "'.$type.'"'
487
        );
488
    }
489
490
    /** @return array Collection of navigation additional fields */
491
    protected function navigationFields($navigationID)
492
    {
493
        $return = array();
494
        // TODO: Optimize queries make one single query with only needed data
495
        foreach ($this->database->fetch('SELECT * FROM `structurefield` WHERE `StructureID` = "' . $navigationID . '" AND `Active` = "1"') as $fieldStructureRow) {
496
            foreach ($this->database->fetch('SELECT * FROM `field` WHERE `FieldID` = "' . $fieldStructureRow['FieldID'] . '"') as $fieldRow) {
497
                $return[$fieldRow['FieldID']] = $fieldRow;
498
            }
499
        }
500
501
        return $return;
502
    }
503
504
    /**
505
     * Generate entity classes.
506
     *
507
     * @param string $namespace Base namespace for generated classes
508
     * @return string Generated PHP code for entity classes
509
     */
510
    public function createEntityClasses($namespace = __NAMESPACE__)
511
    {
512
        $classes = "\n" . 'namespace ' . $namespace . ';';
513
        $classes .= "\n";
514
        $classes .= "\n" . 'use '.$namespace.'\renderable\FieldsTable;';
515
        $classes .= "\n" . 'use '.$namespace.'\field\Row;';
516
        $classes .= "\n" . 'use \samsonframework\core\ViewInterface;';
517
        $classes .= "\n" . 'use \samsonframework\orm\ArgumentInterface;';
518
        $classes .= "\n" . 'use \samsonframework\orm\QueryInterface;';
519
520
        // Iterate all structures
521
        foreach ($this->entityNavigations() as $structureRow) {
522
            $navigationFields = $this->navigationFields($structureRow['StructureID']);
523
            $entityName = $this->entityName($structureRow['Name']);
524
525
            $classes .= $this->createEntityClass(
526
                $structureRow['Name'],
527
                $entityName,
528
                $navigationFields
529
            );
530
531
            $classes .= $this->createQueryClass(
532
                $structureRow['StructureID'],
533
                $structureRow['Name'],
534
                $entityName.'Query',
535
                $navigationFields
536
            );
537
        }
538
539
        // Iterate table structures
540
        foreach ($this->entityNavigations(2) as $structureRow) {
541
            $navigationFields = $this->navigationFields($structureRow['StructureID']);
542
            $entityName = $this->entityName($structureRow['Name']);
543
544
            $rowClassName = $entityName.'TableRow';
545
546
            $classes .= $this->createTableRowClass(
547
                $structureRow['Name'],
548
                $rowClassName,
549
                $navigationFields
550
            );
551
552
            $classes .= $this->createTableClass(
553
                $structureRow['StructureID'],
554
                $structureRow['Name'],
555
                $entityName.'Table',
556
                $navigationFields,
557
                $rowClassName
558
            );
559
560
        }
561
562
        // Make correct code formatting
563
        return str_replace("\t", '    ', $classes);
564
    }
565
566
    /**
567
     * Generator constructor.
568
     * @param DatabaseInterface $database Database instance
569
     */
570
    public function __construct(DatabaseInterface $database)
571
    {
572
        $this->generator = new \samsonphp\generator\Generator();
573
        $this->database = $database;
574
    }
575
}
576
577
//[PHPCOMPRESSOR(remove,end)]
578