Completed
Push — master ( 89322a...8cf2f6 )
by Vitaly
35:11 queued 20:23
created

Generator::getValidName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
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 self 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 self 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->multiComment(array(
412
            'Class for getting "'.$navigationName.'" instances from database',
413
            '@method '.$this->entityName($navigationName).'[] find($page = null, $count = null) Get entities collection',
414
            '@method '.$this->entityName($navigationName).' first() Get entity',
415
            '@method '.$entityName.' where($fieldName, $fieldValue = null, $fieldRelation = ArgumentInterface::EQUAL)',
416
            '@method '.$entityName.' primary($value) Query for chaining',
417
            '@method '.$entityName.' identifier($value) Query for chaining',
418
            '@method '.$entityName.' created($value) Query for chaining',
419
            '@method '.$entityName.' modified($value) Query for chaining',
420
            '@method '.$entityName.' published($value) Query for chaining'
421
        ))->defClass($entityName, '\samsoncms\api\renderable\Collection')
422
        ;
423
424
        // Iterate additional fields
425
        $localizedFieldIDs = array();
426
        $notLocalizedFieldIDs = array();
427
        $allFieldIDs = array();
428
        $allFieldNames = array();
429
        $allFieldValueColumns = array();
430
        $realNames = array();
431
        foreach ($navigationFields as $fieldID => $fieldRow) {
432
            $fieldName = $this->fieldName($fieldRow['Name']);
433
434
            // TODO: Add different method generation depending on their field type
435
            $this->generator->text($this->generateFieldConditionMethod(
436
                $fieldName,
437
                $fieldRow[Field::F_PRIMARY],
438
                $fieldRow[Field::F_TYPE]
439
            ));
440
441
            // Store field metadata
442
            $realNames[$fieldRow['Name']] = $fieldName;
443
            $allFieldIDs[$fieldID] = $fieldName;
444
            $allFieldNames[$fieldName] = $fieldID;
445
            $allFieldValueColumns[$fieldID] = Field::valueColumn($fieldRow[Field::F_TYPE]);
446
            if ($fieldRow[Field::F_LOCALIZED] == 1) {
447
                $localizedFieldIDs[$fieldID] = $fieldName;
448
            } else {
449
                $notLocalizedFieldIDs[$fieldID] = $fieldName;
450
            }
451
        }
452
453
        // TODO: Add generator method generation logic
454
        $class = "\n\t".'/**';
455
        $class .= "\n\t".' * @param ViewInterface $renderer Rendering instance';
456
        $class .= "\n\t".' * @param QueryInterface $query Querying instance';
457
        $class .= "\n\t".' * @param string $locale Localization identifier';
458
        $class .= "\n\t".' */';
459
        $class .= "\n\t".'public function __construct(ViewInterface $renderer, QueryInterface $query = null, $locale = null)';
460
        $class .= "\n\t".'{';
461
        $class .= "\n\t\t".'parent::__construct($query === null ? new dbQuery() : $query, $renderer, $locale);';
462
        $class .= "\n\t".'}'."\n";
463
464
        return $this->generator
465
            ->commentVar('array', 'Collection of real additional field names')
466
            ->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...
467
            ->commentVar('array', 'Collection of navigation identifiers')
468
            ->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...
469
            ->commentVar('string', 'Not transliterated entity name')
470
            ->defClassVar('$identifier', 'protected static', $this->fullEntityName($navigationName))
471
            ->commentVar('array', 'Collection of localized additional fields identifiers')
472
            ->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...
473
            ->commentVar('array', 'Collection of NOT localized additional fields identifiers')
474
            ->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...
475
            ->commentVar('array', 'Collection of localized additional fields identifiers')
476
            ->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...
477
            ->commentVar('array', 'Collection of additional fields value column names')
478
            ->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...
479
            ->commentVar('array', 'Collection of additional field names')
480
            ->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...
481
            ->text($class)
482
            ->endClass()
483
            ->flush()
484
            ;
485
    }
486
487
    /**
488
     * Create entity query PHP class code.
489
     *
490
     * @param integer $navigationID Entity navigation identifier
491
     * @param string $navigationName Original entity name
492
     * @param string $entityName PHP entity name
493
     * @param array $navigationFields Collection of entity additional fields
494
     * @return string Generated entity query PHP class code
495
     */
496 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...
497
    {
498
        $this->generator->multiComment(array(
499
            'Class for getting "'.$navigationName.'" instances from database',
500
            '@method '.$this->entityName($navigationName).'[] find($page = null, $count = null) Get entities collection',
501
            '@method '.$this->entityName($navigationName).' first() Get entity',
502
            '@method '.$entityName.' where($fieldName, $fieldValue = null, $fieldRelation = ArgumentInterface::EQUAL)',
503
            '@method '.$entityName.' primary($value) Query for chaining',
504
            '@method '.$entityName.' identifier($value) Query for chaining',
505
            '@method '.$entityName.' created($value) Query for chaining',
506
            '@method '.$entityName.' modified($value) Query for chaining',
507
            '@method '.$entityName.' published($value) Query for chaining'
508
        ))->defClass($entityName, '\samsoncms\api\query\Entity')
509
        ;
510
511
        // Iterate additional fields
512
        $localizedFieldIDs = array();
513
        $notLocalizedFieldIDs = array();
514
        $allFieldIDs = array();
515
        $allFieldNames = array();
516
        $allFieldValueColumns = array();
517
        $realNames = array();
518
        foreach ($navigationFields as $fieldID => $fieldRow) {
519
            $fieldName = $this->fieldName($fieldRow['Name']);
520
521
            // TODO: Add different method generation depending on their field type
522
            $this->generator->text($this->generateFieldConditionMethod(
523
                $fieldName,
524
                $fieldRow[Field::F_PRIMARY],
525
                $fieldRow[Field::F_TYPE]
526
            ));
527
528
            // Store field metadata
529
            $realNames[$fieldRow['Name']] = $fieldName;
530
            $allFieldIDs[$fieldID] = $fieldName;
531
            $allFieldNames[$fieldName] = $fieldID;
532
            $allFieldValueColumns[$fieldID] = Field::valueColumn($fieldRow[Field::F_TYPE]);
533
            if ($fieldRow[Field::F_LOCALIZED] == 1) {
534
                $localizedFieldIDs[$fieldID] = $fieldName;
535
            } else {
536
                $notLocalizedFieldIDs[$fieldID] = $fieldName;
537
            }
538
        }
539
540
        // TODO: Add generator method generation logic
541
        $class = "\n\t".'/**';
542
        $class .= "\n\t".' * @param QueryInterface $query Rendering instance';
543
        $class .= "\n\t".' * @param string $locale Localization identifier';
544
        $class .= "\n\t".' */';
545
        $class .= "\n\t".'public function __construct(QueryInterface $query = null, $locale = null)';
546
        $class .= "\n\t".'{';
547
        $class .= "\n\t\t".'parent::__construct($query === null ? new dbQuery() : $query, $locale);';
548
        $class .= "\n\t".'}'."\n";
549
550
        return $this->generator
551
            ->commentVar('array', 'Collection of real additional field names')
552
            ->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...
553
            ->commentVar('array', 'Collection of navigation identifiers')
554
            ->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...
555
            ->commentVar('string', 'Not transliterated entity name')
556
            ->defClassVar('$identifier', 'protected static', $this->fullEntityName($navigationName))
557
            ->commentVar('array', 'Collection of localized additional fields identifiers')
558
            ->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...
559
            ->commentVar('array', 'Collection of NOT localized additional fields identifiers')
560
            ->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...
561
            ->commentVar('array', 'Collection of localized additional fields identifiers')
562
            ->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...
563
            ->commentVar('array', 'Collection of additional fields value column names')
564
            ->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...
565
            ->commentVar('array', 'Collection of additional field names')
566
            ->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...
567
            ->text($class)
568
            ->endClass()
569
            ->flush()
570
        ;
571
    }
572
573
    /** @return string Entity state hash */
574
    public function entityHash()
575
    {
576
        // Получим информацию о всех таблицах из БД
577
        return md5(serialize($this->database->fetch(
578
            'SELECT `TABLES`.`TABLE_NAME` as `TABLE_NAME`
579
              FROM `information_schema`.`TABLES` as `TABLES`
580
              WHERE `TABLES`.`TABLE_SCHEMA`="' . $this->database->database() . '";'
581
        )));
582
    }
583
584
    /** @return array Get collection of navigation objects */
585
    protected function entityNavigations($type = 0)
586
    {
587
        return $this->database->fetch('
588
        SELECT * FROM `structure`
589
        WHERE `Active` = "1" AND `Type` = "'.$type.'"'
590
        );
591
    }
592
593
    /** @return array Collection of navigation additional fields */
594
    protected function navigationFields($navigationID)
595
    {
596
        $return = array();
597
        // TODO: Optimize queries make one single query with only needed data
598
        foreach ($this->database->fetch('SELECT * FROM `structurefield` WHERE `StructureID` = "' . $navigationID . '" AND `Active` = "1"') as $fieldStructureRow) {
599
            foreach ($this->database->fetch('SELECT * FROM `field` WHERE `FieldID` = "' . $fieldStructureRow['FieldID'] . '"') as $fieldRow) {
600
                $return[$fieldRow['FieldID']] = $fieldRow;
601
            }
602
        }
603
604
        return $return;
605
    }
606
607
    /**
608
     * Generate entity classes.
609
     *
610
     * @param string $namespace Base namespace for generated classes
611
     * @return string Generated PHP code for entity classes
612
     */
613
    public function createEntityClasses($namespace = __NAMESPACE__)
614
    {
615
        $classes = "\n" . 'namespace ' . $namespace . ';';
616
        $classes .= "\n";
617
        $classes .= "\n" . 'use '.$namespace.'\renderable\FieldsTable;';
618
        $classes .= "\n" . 'use '.$namespace.'\field\Row;';
619
        $classes .= "\n" . 'use \samsonframework\core\ViewInterface;';
620
        $classes .= "\n" . 'use \samson\activerecord\dbQuery;';
621
        $classes .= "\n" . 'use \samsonframework\orm\ArgumentInterface;';
622
        $classes .= "\n" . 'use \samsonframework\orm\QueryInterface;';
623
624
        // Iterate all structures
625
        foreach ($this->entityNavigations() as $structureRow) {
626
            $navigationFields = $this->navigationFields($structureRow['StructureID']);
627
            $entityName = $this->entityName($structureRow['Name']);
628
629
            $classes .= $this->createEntityClass(
630
                $structureRow['Name'],
631
                $entityName,
632
                $navigationFields,
633
                $structureRow['StructureID']
634
            );
635
636
            $classes .= $this->createQueryClass(
637
                $structureRow['StructureID'],
638
                $structureRow['Name'],
639
                $entityName.'Query',
640
                $navigationFields
641
            );
642
643
            $classes .= $this->createCollectionClass(
644
                $structureRow['StructureID'],
645
                $structureRow['Name'],
646
                $entityName.'Collection',
647
                $navigationFields
648
            );
649
        }
650
651
        // Iterate table structures
652
        foreach ($this->entityNavigations(2) as $structureRow) {
653
            $navigationFields = $this->navigationFields($structureRow['StructureID']);
654
            $entityName = $this->entityName($structureRow['Name']);
655
656
            $rowClassName = $entityName.'TableRow';
657
658
            $classes .= $this->createTableRowClass(
659
                $structureRow['Name'],
660
                $rowClassName,
661
                $navigationFields
662
            );
663
664
            $classes .= $this->createTableClass(
665
                $structureRow['StructureID'],
666
                $structureRow['Name'],
667
                $entityName.'Table',
668
                $navigationFields,
669
                $rowClassName
670
            );
671
672
        }
673
674
        // Make correct code formatting
675
        return str_replace("\t", '    ', $classes);
676
    }
677
678
    /**
679
     * Generator constructor.
680
     * @param DatabaseInterface $database Database instance
681
     */
682
    public function __construct(DatabaseInterface $database)
683
    {
684
        $this->generator = new \samsonphp\generator\Generator();
685
        $this->database = $database;
686
    }
687
}
688
689
//[PHPCOMPRESSOR(remove,end)]
690