Completed
Push — master ( 851d6b...2e31f8 )
by Vitaly
10:42 queued 05:39
created

Generator::navigationFields()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 12
rs 9.4285
cc 3
eloc 6
nc 3
nop 1
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 samsoncms\api\query\Generic;
13
use samsonframework\orm\DatabaseInterface;
14
15
/**
16
 * Entity classes generator.
17
 * @package samsoncms\api
18
 */
19
class Generator
20
{
21
    /** @var DatabaseInterface */
22
    protected $database;
23
24
    /** @var \samsonphp\generator\Generator */
25
    protected $generator;
26
27
    /**
28
     * Transliterate string to english.
29
     *
30
     * @param string $string Source string
31
     * @return string Transliterated string
32
     */
33
    protected function transliterated($string)
34
    {
35
        return str_replace(
36
            ' ',
37
            '',
38
            ucwords(iconv("UTF-8", "UTF-8//IGNORE", strtr($string, array(
39
                            "'" => "",
40
                            "`" => "",
41
                            "-" => " ",
42
                            "_" => " ",
43
                            "а" => "a", "А" => "a",
44
                            "б" => "b", "Б" => "b",
45
                            "в" => "v", "В" => "v",
46
                            "г" => "g", "Г" => "g",
47
                            "д" => "d", "Д" => "d",
48
                            "е" => "e", "Е" => "e",
49
                            "ж" => "zh", "Ж" => "zh",
50
                            "з" => "z", "З" => "z",
51
                            "и" => "i", "И" => "i",
52
                            "й" => "y", "Й" => "y",
53
                            "к" => "k", "К" => "k",
54
                            "л" => "l", "Л" => "l",
55
                            "м" => "m", "М" => "m",
56
                            "н" => "n", "Н" => "n",
57
                            "о" => "o", "О" => "o",
58
                            "п" => "p", "П" => "p",
59
                            "р" => "r", "Р" => "r",
60
                            "с" => "s", "С" => "s",
61
                            "т" => "t", "Т" => "t",
62
                            "у" => "u", "У" => "u",
63
                            "ф" => "f", "Ф" => "f",
64
                            "х" => "h", "Х" => "h",
65
                            "ц" => "c", "Ц" => "c",
66
                            "ч" => "ch", "Ч" => "ch",
67
                            "ш" => "sh", "Ш" => "sh",
68
                            "щ" => "sch", "Щ" => "sch",
69
                            "ъ" => "", "Ъ" => "",
70
                            "ы" => "y", "Ы" => "y",
71
                            "ь" => "", "Ь" => "",
72
                            "э" => "e", "Э" => "e",
73
                            "ю" => "yu", "Ю" => "yu",
74
                            "я" => "ya", "Я" => "ya",
75
                            "і" => "i", "І" => "i",
76
                            "ї" => "yi", "Ї" => "yi",
77
                            "є" => "e", "Є" => "e"
78
                        )
79
                    )
80
                )
81
            )
82
        );
83
    }
84
85
    /**
86
     * Get class constant name by its value.
87
     *
88
     * @param string $value Constant value
89
     * @param string $className Class name
90
     * @return string Full constant name
91
     */
92
    protected function constantNameByValue($value, $className = Field::ENTITY)
93
    {
94
        // Get array where class constants are values and their values are keys
95
        $nameByValue = array_flip((new \ReflectionClass($className))->getConstants());
96
97
        // Try to find constant by its value
98
        if (null !== $nameByValue[$value]) {
99
            // Return constant name
100
            return $nameByValue[$value];
101
        }
102
103
        return '';
104
    }
105
106
    /**
107
     * Get correct entity name.
108
     *
109
     * @param string $navigationName Original navigation entity name
110
     * @return string Correct PHP-supported entity name
111
     */
112
    protected function entityName($navigationName)
113
    {
114
        return ucfirst($this->getValidName($this->transliterated($navigationName)));
115
    }
116
	
117
    /**
118
     * Remove all wrong characters from entity name
119
     *
120
     * @param string $navigationName Original navigation entity name
121
     * @return string Correct PHP-supported entity name
122
     */
123
    protected function getValidName($navigationName)
124
    {
125
        return preg_replace('/(^\d*)|([^\w\d_])/', '', $navigationName);
126
    }
127
128
    /**
129
     * Get correct full entity name with name space.
130
     *
131
     * @param string $navigationName Original navigation entity name
132
     * @param string $namespace Namespace
133
     * @return string Correct PHP-supported entity name
134
     */
135
    protected function fullEntityName($navigationName, $namespace = __NAMESPACE__)
136
    {
137
        return str_replace('\\', '\\\\' , '\\'.$namespace.'\\'.$this->entityName($navigationName));
0 ignored issues
show
Coding Style introduced by
Space found before comma in function call
Loading history...
138
    }
139
140
    /**
141
     * Get correct field name.
142
     *
143
     * @param string $fieldName Original field name
144
     * @return string Correct PHP-supported field name
145
     */
146
    protected function fieldName($fieldName)
147
    {
148
        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...
149
    }
150
151
    /**
152
     * Get additional field type in form of Field constant name
153
     * by database additional field type identifier.
154
     *
155
     * @param integer $fieldType Additional field type identifier
156
     * @return string Additional field type constant
157
     */
158
    protected function additionalFieldType($fieldType)
159
    {
160
        return 'Field::'.$this->constantNameByValue($fieldType);
161
    }
162
163
    /**
164
     * Generate Query::where() analog for specific field.
165
     *
166
     * @param string $fieldName Field name
167
     * @param string $fieldId Field primary identifier
168
     * @param string $fieldType Field PHP type
169
     * @return string Generated PHP method code
170
     */
171 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...
172
    {
173
        $code = "\n\t" . '/**';
174
        $code .= "\n\t" . ' * Add '.$fieldName.'(#' . $fieldId . ') field query condition.';
175
        $code .= "\n\t" . ' * @param '.Field::phpType($fieldType).' $value Field value';
176
        $code .= "\n\t" . ' * @return $this Chaining';
177
        $code .= "\n\t" . ' * @see Generic::where()';
178
        $code .= "\n\t" . ' */';
179
        $code .= "\n\t" . 'public function ' . $fieldName . '($value)';
180
        $code .= "\n\t" . "{";
181
        $code .= "\n\t\t" . 'return $this->where("'.$fieldName.'", $value);';
182
183
        return $code . "\n\t" . "}"."\n";
184
    }
185
186
    /**
187
     * Generate Query::where() analog for specific field.
188
     *
189
     * @param string $fieldName Field name
190
     * @param string $fieldId Field primary identifier
191
     * @param string $fieldType Field PHP type
192
     * @return string Generated PHP method code
193
     */
194 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...
195
    {
196
        $code = "\n\t" . '/**';
197
        $code .= "\n\t" . ' * Add '.$fieldName.'(#' . $fieldId . ') field query condition.';
198
        $code .= "\n\t" . ' * @param '.Field::phpType($fieldType).' $value Field value';
199
        $code .= "\n\t" . ' * @return $this Chaining';
200
        $code .= "\n\t" . ' * @see Generic::where()';
201
        $code .= "\n\t" . ' */';
202
        $code .= "\n\t" . 'public function ' . $fieldName . '($value)';
203
        $code .= "\n\t" . "{";
204
        $code .= "\n\t\t" . 'return $this->where("'.$fieldName.'", $value);';
205
206
        return $code . "\n\t" . "}"."\n";
207
    }
208
209
    /**
210
     * Create entity PHP class code.
211
     *
212
     * @param string $navigationName Original entity name
213
     * @param string $entityName PHP entity name
214
     * @param array $navigationFields Collection of entity additional fields
215
     * @param int $navigationId Entity database identifier
216
     * @return string Generated entity query PHP class code
217
     */
218
    protected function createEntityClass($navigationName, $entityName, $navigationFields, $navigationId)
219
    {
220
        $this->generator
221
            ->multiComment(array('"'.$navigationName.'" entity class'))
222
            ->defClass($entityName, 'Entity')
223
            ->commentVar('string', 'Entity full class name')
224
            ->defClassConst('ENTITY', $this->fullEntityName($entityName))
225
            ->commentVar('string', 'Entity manager full class name')
226
            ->defClassConst('MANAGER', $this->fullEntityName($entityName.'Query'))
227
            ->commentVar('string', 'Entity database identifier')
228
            ->defClassConst('IDENTIFIER', $navigationId)
229
            ->commentVar('string', 'Not transliterated entity name')
230
            ->defClassVar('$viewName', 'protected static');
231
232
        // Get old AR collections of metadata
233
        $select = \samson\activerecord\material::$_sql_select;
234
        $attributes = \samson\activerecord\material::$_attributes;
235
        $map = \samson\activerecord\material::$_map;
236
        $from = \samson\activerecord\material::$_sql_from;
237
        $group = \samson\activerecord\material::$_own_group;
238
        $relationAlias = \samson\activerecord\material::$_relation_alias;
239
        $relationType = \samson\activerecord\material::$_relation_type;
240
        $relations = \samson\activerecord\material::$_relations;
241
242
243
        // Add SamsonCMS material needed data
244
        $select['this'] = ' STRAIGHT_JOIN ' . $select['this'];
245
        $from['this'] .= "\n" . 'LEFT JOIN ' . dbMySQLConnector::$prefix . 'materialfield as _mf on ' . dbMySQLConnector::$prefix . 'material.MaterialID = _mf.MaterialID';
246
        $group[] = dbMySQLConnector::$prefix . 'material.MaterialID';
247
248
        foreach ($navigationFields as $fieldID => $fieldRow) {
249
            $fieldName = $this->fieldName($fieldRow['Name']);
250
251
            $attributes[$fieldName] = $fieldName;
252
            $map[$fieldName] = dbMySQLConnector::$prefix . 'material.' . $fieldName;
253
254
            $equal = '((_mf.FieldID = ' . $fieldID . ')&&(_mf.locale ' . ($fieldRow['local'] ? ' = "@locale"' : 'IS NULL') . '))';
255
256
            // Save additional field
257
            $select['this'] .= "\n\t\t" . ',MAX(IF(' . $equal . ', _mf.`' . Field::valueColumn($fieldRow['Type']) . '`, NULL)) as `' . $fieldName . '`';
258
259
            $this->generator
260
                ->commentVar('string', $fieldRow['Description'] . ' Field #' . $fieldID . ' variable name')
261
                ->defClassConst('F_' . $fieldName, $fieldName)
262
                ->commentVar(Field::phpType($fieldRow['Type']), $fieldRow['Description'] . ' Field #' . $fieldID)
263
                ->defClassVar('$' . $fieldName, 'public');
264
        }
265
266
        return $this->generator
267
            ->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...
268
            ->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...
269
            ->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...
270
            ->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...
271
            ->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...
272
            ->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...
273
            ->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...
274
            ->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...
275
            ->endclass()
276
            ->flush();
277
    }
278
279
    /**
280
     * Generate FieldsTable::values() analog for specific field.
281
     *
282
     * @param string $fieldName Field name
283
     * @param string $fieldId Field primary identifier
284
     * @param string $fieldType Field PHP type
285
     * @return string Generated PHP method code
286
     */
287
    protected function generateTableFieldMethod($fieldName, $fieldId, $fieldType)
288
    {
289
        $code = "\n\t" . '/**';
290
        $code .= "\n\t" . ' * Get table column '.$fieldName.'(#' . $fieldId . ') values.';
291
        $code .= "\n\t" . ' * @return array Collection('.Field::phpType($fieldType).') of table column values';
292
        $code .= "\n\t" . ' */';
293
        $code .= "\n\t" . 'public function ' . $fieldName . '()';
294
        $code .= "\n\t" . "{";
295
        $code .= "\n\t\t" . 'return $this->values('.$fieldId.');';
296
297
        return $code . "\n\t" . "}"."\n";
298
    }
299
300
    /**
301
     * Create fields table row PHP class code.
302
     *
303
     * @param string $navigationName Original entity name
304
     * @param string $entityName PHP entity name
305
     * @param array $navigationFields Collection of entity additional fields
306
     * @return string Generated entity query PHP class code
307
     */
308
    protected function createTableRowClass($navigationName, $entityName, $navigationFields)
309
    {
310
        $class = "\n";
311
        $class .= "\n" . '/**';
312
        $class .= "\n" . ' * Class for getting "'.$navigationName.'" fields table rows';
313
        $class .= "\n" . ' */';
314
        $class .= "\n" . 'class ' . $entityName . ' extends Row';
315
        $class .= "\n" . '{';
316
317
        // Iterate additional fields
318
        $constants = '';
319
        $variables = '';
320
        foreach ($navigationFields as $fieldID => $fieldRow) {
321
            $fieldName = $this->fieldName($fieldRow['Name']);
322
323
            $constants .= "\n\t" . '/** ' . Field::phpType($fieldRow['Type']) . ' '.$fieldRow['Description'].' Field #' . $fieldID . ' variable name */';
324
            // Store original field name
325
            $constants .= "\n\t" . 'const F_' . strtoupper($fieldName) . ' = "'.$fieldName.'";';
326
327
            $variables .= "\n\t" . '/** ' . Field::phpType($fieldRow['Type']) . ' '.$fieldRow['Description'].' Field #' . $fieldID . ' row value */';
328
            $variables .= "\n\t" . 'public $' . $fieldName . ';';
329
        }
330
331
        $class .= $constants;
332
        $class .= "\n\t";
333
        $class .= $variables;
334
        $class .= "\n" . '}';
335
336
        return $class;
337
    }
338
339
    /**
340
     * Create fields table PHP class code.
341
     *
342
     * @param integer $navigationID     Entity navigation identifier
343
     * @param string  $navigationName   Original entity name
344
     * @param string  $entityName       PHP entity name
345
     * @param array   $navigationFields Collection of entity additional fields
346
     * @param string  $rowClassName Row class name
347
     *
348
     * @return string Generated entity query PHP class code
349
     * @throws exception\AdditionalFieldTypeNotFound
350
     */
351
    protected function createTableClass($navigationID, $navigationName, $entityName, $navigationFields, $rowClassName)
352
    {
353
        $this->generator
354
            ->multiComment(array('Class for getting "'.$navigationName.'" fields table'))
355
            ->defClass($entityName, 'FieldsTable');
356
357
        // Iterate additional fields
358
        $fields = array();
359
        foreach ($navigationFields as $fieldID => $fieldRow) {
360
            $fieldName = $this->fieldName($fieldRow['Name']);
361
362
            $this->generator
363
                ->text($this->generateTableFieldMethod(
364
                    $fieldName,
365
                    $fieldRow[Field::F_PRIMARY],
366
                    $fieldRow[Field::F_TYPE]
367
                ))
368
                ->commentVar(Field::phpType($fieldRow['Type']), $fieldRow['Description'] . ' Field #' . $fieldID . ' variable name')
369
                ->defClassConst('F_' . $fieldName, $fieldName);
370
371
            // Collection original to new one field names
372
            $fields[$fieldRow['Name']] = $fieldName;
373
        }
374
375
        // TODO: Add generator method generation logic
376
        $class = "\n\t".'/**';
377
        $class .= "\n\t".' * @param QueryInterface $query Database query instance';
378
        $class .= "\n\t".' * @param ViewInterface $renderer Rendering instance';
379
        $class .= "\n\t".' * @param integer $entityID Entity identifier to whom this table belongs';
380
        $class .= "\n\t".' * @param string $locale Localization identifier';
381
        $class .= "\n\t".' */';
382
        $class .= "\n\t".'public function __construct(QueryInterface $query, ViewInterface $renderer, $entityID, $locale = null)';
383
        $class .= "\n\t".'{';
384
        $class .= "\n\t\t".'parent::__construct($query, $renderer, static::$navigationIDs, $entityID, $locale);';
385
        $class .= "\n\t".'}'."\n";
386
387
        $this->generator->text($class);
388
389
        return $this->generator
390
            ->commentVar('array', 'Collection of real additional field names')
391
            ->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...
392
            ->commentVar('array', 'Collection of navigation identifiers')
393
            ->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...
394
            ->commentVar('string', 'Row class name')
395
            ->defClassVar('$identifier', 'protected', $this->fullEntityName($rowClassName))
396
            ->endClass()
397
            ->flush();
398
    }
399
400
    /**
401
     * Create entity query PHP class code.
402
     *
403
     * @param integer $navigationID Entity navigation identifier
404
     * @param string $navigationName Original entity name
405
     * @param string $entityName PHP entity name
406
     * @param array $navigationFields Collection of entity additional fields
407
     * @return string Generated entity query PHP class code
408
     */
409 View Code Duplication
    protected function createCollectionClass($navigationID, $navigationName, $entityName, $navigationFields)
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...
410
    {
411
        $this->generator
412
            ->multiComment(array('Class for getting "'.$navigationName.'" instances from database',))
413
            ->defClass($entityName, '\samsoncms\api\renderable\Collection')
414
        ;
415
416
        // Iterate additional fields
417
        $localizedFieldIDs = array();
418
        $notLocalizedFieldIDs = array();
419
        $allFieldIDs = array();
420
        $allFieldNames = array();
421
        $allFieldValueColumns = array();
422
        $realNames = array();
423
        foreach ($navigationFields as $fieldID => $fieldRow) {
424
            $fieldName = $this->fieldName($fieldRow['Name']);
425
426
            // TODO: Add different method generation depending on their field type
427
            $this->generator->text($this->generateFieldConditionMethod(
428
                $fieldName,
429
                $fieldRow[Field::F_PRIMARY],
430
                $fieldRow[Field::F_TYPE]
431
            ));
432
433
            // Store field metadata
434
            $realNames[$fieldRow['Name']] = $fieldName;
435
            $allFieldIDs[$fieldID] = $fieldName;
436
            $allFieldNames[$fieldName] = $fieldID;
437
            $allFieldValueColumns[$fieldID] = Field::valueColumn($fieldRow[Field::F_TYPE]);
438
            if ($fieldRow[Field::F_LOCALIZED] == 1) {
439
                $localizedFieldIDs[$fieldID] = $fieldName;
440
            } else {
441
                $notLocalizedFieldIDs[$fieldID] = $fieldName;
442
            }
443
        }
444
445
        // TODO: Add generator method generation logic
446
        $class = "\n\t".'/**';
447
        $class .= "\n\t".' * @param ViewInterface $renderer Rendering instance';
448
        $class .= "\n\t".' * @param QueryInterface $query Querying instance';
449
        $class .= "\n\t".' * @param string $locale Localization identifier';
450
        $class .= "\n\t".' */';
451
        $class .= "\n\t".'public function __construct(ViewInterface $renderer, QueryInterface $query = null, $locale = null)';
452
        $class .= "\n\t".'{';
453
        $class .= "\n\t\t".'parent::__construct($query === null ? new dbQuery() : $query, $renderer, $locale);';
454
        $class .= "\n\t".'}'."\n";
455
456
        return $this->generator
457
            ->commentVar('array', 'Collection of real additional field names')
458
            ->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...
459
            ->commentVar('array', 'Collection of navigation identifiers')
460
            ->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...
461
            ->commentVar('string', 'Not transliterated entity name')
462
            ->defClassVar('$identifier', 'protected static', $this->fullEntityName($navigationName))
463
            ->commentVar('array', 'Collection of localized additional fields identifiers')
464
            ->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...
465
            ->commentVar('array', 'Collection of NOT localized additional fields identifiers')
466
            ->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...
467
            ->commentVar('array', 'Collection of localized additional fields identifiers')
468
            ->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...
469
            ->commentVar('array', 'Collection of additional fields value column names')
470
            ->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...
471
            ->commentVar('array', 'Collection of additional field names')
472
            ->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...
473
            ->text($class)
474
            ->endClass()
475
            ->flush()
476
            ;
477
    }
478
479
    /**
480
     * Create entity query PHP class code.
481
     *
482
     * @param integer $navigationID Entity navigation identifier
483
     * @param string $navigationName Original entity name
484
     * @param string $entityName PHP entity name
485
     * @param array $navigationFields Collection of entity additional fields
486
     * @return string Generated entity query PHP class code
487
     */
488 View Code Duplication
    protected function createQueryClass($navigationID, $navigationName, $entityName, $navigationFields)
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...
489
    {
490
        $this->generator
491
            ->multiComment(array('Class for getting "'.$navigationName.'" instances from database'))
492
            ->defClass($entityName, '\samsoncms\api\query\Entity')
493
        ;
494
495
        // Iterate additional fields
496
        $localizedFieldIDs = array();
497
        $notLocalizedFieldIDs = array();
498
        $allFieldIDs = array();
499
        $allFieldNames = array();
500
        $allFieldValueColumns = array();
501
        $realNames = array();
502
        foreach ($navigationFields as $fieldID => $fieldRow) {
503
            $fieldName = $this->fieldName($fieldRow['Name']);
504
505
            // TODO: Add different method generation depending on their field type
506
            $this->generator->text($this->generateFieldConditionMethod(
507
                $fieldName,
508
                $fieldRow[Field::F_PRIMARY],
509
                $fieldRow[Field::F_TYPE]
510
            ));
511
512
            // Store field metadata
513
            $realNames[$fieldRow['Name']] = $fieldName;
514
            $allFieldIDs[$fieldID] = $fieldName;
515
            $allFieldNames[$fieldName] = $fieldID;
516
            $allFieldValueColumns[$fieldID] = Field::valueColumn($fieldRow[Field::F_TYPE]);
517
            if ($fieldRow[Field::F_LOCALIZED] == 1) {
518
                $localizedFieldIDs[$fieldID] = $fieldName;
519
            } else {
520
                $notLocalizedFieldIDs[$fieldID] = $fieldName;
521
            }
522
        }
523
524
        // TODO: Add generator method generation logic
525
        $class = "\n\t".'/**';
526
        $class .= "\n\t".' * @param QueryInterface $query Rendering instance';
527
        $class .= "\n\t".' * @param string $locale Localization identifier';
528
        $class .= "\n\t".' */';
529
        $class .= "\n\t".'public function __construct(QueryInterface $query = null, $locale = null)';
530
        $class .= "\n\t".'{';
531
        $class .= "\n\t\t".'parent::__construct($query === null ? new dbQuery() : $query, $locale);';
532
        $class .= "\n\t".'}'."\n";
533
534
        return $this->generator
535
            ->commentVar('array', 'Collection of real additional field names')
536
            ->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...
537
            ->commentVar('array', 'Collection of navigation identifiers')
538
            ->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...
539
            ->commentVar('string', 'Not transliterated entity name')
540
            ->defClassVar('$identifier', 'protected static', $this->fullEntityName($navigationName))
541
            ->commentVar('array', 'Collection of localized additional fields identifiers')
542
            ->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...
543
            ->commentVar('array', 'Collection of NOT localized additional fields identifiers')
544
            ->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...
545
            ->commentVar('array', 'Collection of localized additional fields identifiers')
546
            ->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...
547
            ->commentVar('array', 'Collection of additional fields value column names')
548
            ->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...
549
            ->commentVar('array', 'Collection of additional field names')
550
            ->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...
551
            ->text($class)
552
            ->endClass()
553
            ->flush()
554
        ;
555
    }
556
557
    /** @return string Entity state hash */
558
    public function entityHash()
559
    {
560
        // Получим информацию о всех таблицах из БД
561
        return md5(serialize($this->database->fetch(
562
            'SELECT `TABLES`.`TABLE_NAME` as `TABLE_NAME`
563
              FROM `information_schema`.`TABLES` as `TABLES`
564
              WHERE `TABLES`.`TABLE_SCHEMA`="' . $this->database->database() . '";'
565
        )));
566
    }
567
568
    /** @return array Get collection of navigation objects */
569
    protected function entityNavigations($type = 0)
570
    {
571
        return $this->database->fetch('
572
        SELECT * FROM `structure`
573
        WHERE `Active` = "1" AND `Type` = "'.$type.'"'
574
        );
575
    }
576
577
    /** @return array Collection of navigation additional fields */
578
    protected function navigationFields($navigationID)
579
    {
580
        $return = array();
581
        // TODO: Optimize queries make one single query with only needed data
582
        foreach ($this->database->fetch('SELECT * FROM `structurefield` WHERE `StructureID` = "' . $navigationID . '" AND `Active` = "1"') as $fieldStructureRow) {
583
            foreach ($this->database->fetch('SELECT * FROM `field` WHERE `FieldID` = "' . $fieldStructureRow['FieldID'] . '"') as $fieldRow) {
584
                $return[$fieldRow['FieldID']] = $fieldRow;
585
            }
586
        }
587
588
        return $return;
589
    }
590
591
    /**
592
     * Generate entity classes.
593
     *
594
     * @param string $namespace Base namespace for generated classes
595
     * @return string Generated PHP code for entity classes
596
     */
597
    public function createEntityClasses($namespace = __NAMESPACE__)
598
    {
599
        $classes = "\n" . 'namespace ' . $namespace . ';';
600
        $classes .= "\n";
601
        $classes .= "\n" . 'use '.$namespace.'\renderable\FieldsTable;';
602
        $classes .= "\n" . 'use '.$namespace.'\field\Row;';
603
        $classes .= "\n" . 'use \samsonframework\core\ViewInterface;';
604
        $classes .= "\n" . 'use \samson\activerecord\dbQuery;';
605
        $classes .= "\n" . 'use \samsonframework\orm\ArgumentInterface;';
606
        $classes .= "\n" . 'use \samsonframework\orm\QueryInterface;';
607
608
        // Iterate all structures
609
        foreach ($this->entityNavigations() as $structureRow) {
610
            $navigationFields = $this->navigationFields($structureRow['StructureID']);
611
            $entityName = $this->entityName($structureRow['Name']);
612
613
            $classes .= $this->createEntityClass(
614
                $structureRow['Name'],
615
                $entityName,
616
                $navigationFields,
617
                $structureRow['StructureID']
618
            );
619
620
            $classes .= $this->createQueryClass(
621
                $structureRow['StructureID'],
622
                $structureRow['Name'],
623
                $entityName.'Query',
624
                $navigationFields
625
            );
626
627
            $classes .= $this->createCollectionClass(
628
                $structureRow['StructureID'],
629
                $structureRow['Name'],
630
                $entityName.'Collection',
631
                $navigationFields
632
            );
633
        }
634
635
        // Iterate table structures
636
        foreach ($this->entityNavigations(2) as $structureRow) {
637
            $navigationFields = $this->navigationFields($structureRow['StructureID']);
638
            $entityName = $this->entityName($structureRow['Name']);
639
640
            $rowClassName = $entityName.'TableRow';
641
642
            $classes .= $this->createTableRowClass(
643
                $structureRow['Name'],
644
                $rowClassName,
645
                $navigationFields
646
            );
647
648
            $classes .= $this->createTableClass(
649
                $structureRow['StructureID'],
650
                $structureRow['Name'],
651
                $entityName.'Table',
652
                $navigationFields,
653
                $rowClassName
654
            );
655
656
        }
657
658
        // Make correct code formatting
659
        return str_replace("\t", '    ', $classes);
660
    }
661
662
    /**
663
     * Generator constructor.
664
     * @param DatabaseInterface $database Database instance
665
     */
666
    public function __construct(DatabaseInterface $database)
667
    {
668
        $this->generator = new \samsonphp\generator\Generator();
669
        $this->database = $database;
670
    }
671
}
672
673
//[PHPCOMPRESSOR(remove,end)]
674