ModelCompiler   D
last analyzed

Complexity

Total Complexity 84

Size/Duplication

Total Lines 691
Duplicated Lines 52.39 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 84
lcom 1
cbo 5
dl 362
loc 691
rs 4.4858
c 0
b 0
f 0

20 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 7 7 2
A replaceAndStore() 0 22 1
A getOutputFilename() 0 6 1
A replaceNamespaceModelExtend() 0 6 1
C addFillable() 19 29 8
B addEnumFields() 6 32 5
C addRules() 19 32 8
A setTimeStamps() 0 11 2
A setPrimaryKey() 0 12 1
C addBelongsTo() 3 49 7
B addReverseRelationship() 3 53 7
B replaceEagerCode() 49 49 5
B replaceRelationshipTables() 86 86 3
A replaceSearchConditions() 0 8 1
A getSearchConditions() 22 22 2
C getConditionStubByField() 30 30 7
A replaceSortConditions() 22 22 3
B replaceReverseRelationshipsFunctions() 29 29 4
A replaceCheckbox() 13 13 1
C replaceSimpleFilter() 54 54 15

How to fix   Duplicated Code    Complexity   

Duplicated Code

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

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like ModelCompiler often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ModelCompiler, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Scaffolder\Compilers\Core;
4
5
use Illuminate\Support\Facades\File;
6
use Scaffolder\Compilers\AbstractCompiler;
7
use Scaffolder\Compilers\Support\FileToCompile;
8
use Scaffolder\Compilers\Support\PathParser;
9
use Scaffolder\Support\Directory;
10
use Scaffolder\Support\CamelCase;
11
12
class ModelCompiler extends AbstractCompiler
13
{
14
	protected $cachePrefix 	= 'model_';
15
	protected $stubFilename = 'Model/Model.php' ;
16
17 View Code Duplication
	public function __construct($scaffolderConfig, $modelData = null, $stubName = null)
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...
18
	{
19
		if ($stubName)
20
			$this->stubFilename = $stubName;
21
		$this->stubsDirectory = __DIR__ . '/../../../../stubs/Api/';
22
		parent::__construct($scaffolderConfig, $modelData);
23
	}
24
25
	/**
26
	 * Replace and store the Stub.
27
	 *
28
	 * @return string
29
	 */
30
	public function replaceAndStore()
31
	{
32
		
33
		return $this->replaceNamespace()
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->replaceNam...modelData->modelHash)); (Scaffolder\Compilers\Core\ModelCompiler) is incompatible with the return type declared by the abstract method Scaffolder\Compilers\Abs...mpiler::replaceAndStore of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
34
				->replaceNamespaceModelExtend()
35
				->setPrimaryKey()
36
				->setTimeStamps()
37
				->addFillable()
38
				->addEnumFields()
39
				->addRules()
40
				->addBelongsTo()
41
				->addReverseRelationship()
42
				->replaceEagerCode()
43
				->replaceRelationshipTables()
44
				->replaceSearchConditions()
45
				->replaceSimpleFilter()
46
				->replaceSortConditions()
47
				->replaceReverseRelationshipsFunctions()
48
				->replaceCheckbox()
49
				->store(new FileToCompile(false, $this->modelData->modelHash));
50
		
51
	}
52
	
53
	/**
54
	 * Get output filename
55
	 *
56
	 *
57
	 * @return $this
58
	 */
59
	protected function getOutputFilename()
60
	{
61
		$folder = PathParser::parse($this->scaffolderConfig->generator->paths->models) ;
62
63
		return $folder .  $this->modelName . '.php';
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $folder . $this->modelName . '.php'; (string) is incompatible with the return type declared by the abstract method Scaffolder\Compilers\Abs...iler::getOutputFilename of type Scaffolder\Compilers\AbstractCompiler.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
64
	}
65
66
	
67
68
	/**
69
	 * Replace the namespace which the model extends
70
	 *
71
	 * @param $this->scaffolderConfig
72
	 *
73
	 * @return $this
74
	 */
75
	private function replaceNamespaceModelExtend()
76
	{
77
		$this->stub = str_replace('{{namespace_model_extend}}', $this->scaffolderConfig->generator->inheritance->model, $this->stub);
78
79
		return $this;
80
	}
81
82
	/**
83
	 * Add fillable.
84
	 *
85
	 * @return $this
86
	 */
87
	private function addFillable()
88
	{
89
		$fields = '';
90
		$firstIteration = true;
91
92 View Code Duplication
		foreach ($this->modelData->fields as $field)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
93
		{
94
			if($field->index == "primary")
95
				continue ;
96
			if($this->modelData->timeStamps && $field->name == "created_at")
97
				continue ;
98
			if($this->modelData->timeStamps && $field->name == "updated_at")
99
				continue ;
100
101
			if ($firstIteration)
102
			{
103
				$fields .= sprintf("'%s'," . PHP_EOL, $field->name);
104
				$firstIteration = false;
105
			}
106
			else
107
			{
108
				$fields .= sprintf("\t\t'%s'," . PHP_EOL, $field->name);
109
			}
110
		}
111
112
		$this->stub = str_replace('{{fillable}}', $fields, $this->stub);
113
114
		return $this;
115
	}
116
117
	private function addEnumFields() {
118
119
		$items = '';
0 ignored issues
show
Unused Code introduced by
$items 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...
120
		$arrays = '';
121
		
122
		foreach ($this->modelData->fields as $field) {
123
			$enumStub = File::get($this->stubsDirectory . '/Model/ModelEnum.php');
124
125
			if ($field->type->db == "enum") {
126
				$items = '';
127
				
128 View Code Duplication
				foreach ($field->options as $key => $option) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
129
					$items .= "'" . $option . "'";
130
					if ($key < (count($field->options) - 1))
131
						$items .= ", ";
132
133
				}
134
135
136
				$enumStub = str_replace('{{field_options}}', $items, $enumStub);
137
				$enumStub = str_replace('{{field_name}}', $field->name, $enumStub);	
138
					
139
				$arrays .= $enumStub;
140
141
				
142
			}
143
		}
144
145
		$this->stub = str_replace('{{enum}}', $arrays, $this->stub);
146
147
		return $this;
148
	}
149
150
	/**
151
	 * Set validations.
152
	 *
153
	 *
154
	 * @return $this
155
	 */
156
	private function addRules()
157
	{
158
		$fields = '';
159
		$firstIteration = true;
160
161 View Code Duplication
		foreach ($this->modelData->fields as $field)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
162
		{
163
			if($field->index == "primary")
164
				continue ;
165
			if($this->modelData->timeStamps && $field->name == "created_at")
166
				continue ;
167
			if($this->modelData->timeStamps && $field->name == "updated_at")
168
				continue ;
169
170
			if ($firstIteration)
171
			{
172
				$fields .= sprintf("'%s' => '%s'," . PHP_EOL, $field->name, $field->validations);
173
				$firstIteration = false;
174
			}
175
			else
176
			{
177
				$fields .= sprintf("\t\t\t'%s' => '%s'," . PHP_EOL, $field->name, $field->validations);
178
			}
179
		}
180
181
		$fields = str_replace('unique','unique:'.$this->modelData->tableName,$fields);
182
		//var_dump($fields);
183
184
		$this->stub = str_replace('{{validations}}', $fields, $this->stub);
185
186
		return $this;
187
	}
188
189
	/**
190
	 * Set the timestamps value.
191
	 *
192
	 */
193
	private function setTimeStamps()
194
	{
195
		if($this->modelData->timeStamps)
196
		{
197
			$this->stub = str_replace('{{timestamps}}', ' ', $this->stub);
198
		} else {
199
			$this->stub = str_replace('{{timestamps}}', 'public $timestamps = false;', $this->stub);
200
		}
201
202
		return $this;
203
	}
204
205
	/**
206
	 *  Set the primary key.
207
	 *
208
	 */
209
	private function setPrimaryKey()
210
	{
211
		$primaryKey = '// Using default primary key' . PHP_EOL;
0 ignored issues
show
Unused Code introduced by
$primaryKey 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...
212
213
		$field = $this->getPrimaryKeyField() ;
214
215
		$primaryKey = 'protected $primaryKey = \'' . $field->name . '\';' . PHP_EOL;
216
217
		$this->stub = str_replace('{{primaryAttribute}}', $primaryKey, $this->stub);
218
219
		return $this;
220
	}
221
222
	/**
223
	 * Add belongsTo Relationships.
224
	 *
225
	 *
226
	 * @return $this
227
	 */
228
	private function addBelongsTo()
229
	{
230
		$functions = '';
231
232
		$eagerArray = [];
233
		
234
		foreach ($this->modelData->fields as $field)
235
		{
236
			
237
			// Check foreign key
238
			if (isset($field->foreignKey->relationship))
239
			{
240
				$belongsToStub = "";
241
				$functionName = $field->foreignKey->table;
242
243
				if ($field->foreignKey->relationship == "belongsTo") {
244
					$belongsToOriginalStub = File::get($this->stubsDirectory . '/Model/ModelBelongsTo.php');
245
					$belongsToStub = str_replace('{{foreign_model}}', CamelCase::convertToCamelCase($field->foreignKey->table), $belongsToOriginalStub);
246
					$belongsToStub = str_replace('{{field}}', $field->name, $belongsToStub);
247
					$belongsToStub = str_replace('{{foreign_field}}', $field->foreignKey->field, $belongsToStub);
248
				}
249
				elseif ($field->foreignKey->relationship == "belongsToMany") {
250
					$belongsToOriginalStub = File::get($this->stubsDirectory . '/Model/ModelBelongsToMany.php');
251
					$functionName = CamelCase::pluralize($field->foreignKey->table);
252
					$belongsToStub = str_replace('{{foreign_model}}', CamelCase::convertToCamelCase($field->foreignKey->table), $belongsToOriginalStub);
253
					$belongsToStub = str_replace('{{foreign_key}}', $field->name, $belongsToStub);
254
					$belongsToStub = str_replace('{{related_field}}', $field->foreignKey->field, $belongsToStub);
255
					$belongsToStub = str_replace('{{table_name}}', $field->foreignKey->table, $belongsToStub);
256
				}
257
				
258
				$belongsToStub = str_replace('{{foreign_table}}', $functionName, $belongsToStub);
259
				$belongsToStub = str_replace('{{model_namespace}}', $this->scaffolderConfig->generator->namespaces->models, $belongsToStub);
260
				
261
				$functions .= $belongsToStub ;
262
263 View Code Duplication
				if(isset($field->foreignKey->eager) && $field->foreignKey->eager){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
264
					array_push($eagerArray, "'".$field->foreignKey->table."'");
265
				}
266
			}
267
268
			
269
		}
270
271
		$this->stub = str_replace('{{belongsTo}}', $functions, $this->stub);
272
273
		$this->stub = str_replace('{{eager}}', join("," , $eagerArray) , $this->stub);
274
275
		return $this;
276
	}
277
278
	private function addReverseRelationship()
279
	{
280
		$functions = '';
281
282
		$eagerArray = [];
283
284
		foreach ($this->modelData->reverseRelationships as $relationship)
285
		{
286
			
287
			// Check foreign key
288
			if ($relationship->foreignKey)
289
			{
290
				$reverseRelationshipStub = "";
0 ignored issues
show
Unused Code introduced by
$reverseRelationshipStub 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...
291
				$functionName = '';
0 ignored issues
show
Unused Code introduced by
$functionName 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...
292
				if ($relationship->type == "hasOne")
293
					$functionName = strtolower($relationship->modelName);
294
				else 
295
					$functionName = CamelCase::pluralize(strtolower($relationship->modelName));
296
				
297
				if ($relationship->type == "belongsToMany") {
298
					$reverseRelationshipOriginalStub = File::get($this->stubsDirectory . '/Model/ModelBelongsToMany.php');
299
					$reverseRelationshipStub = str_replace('{{foreign_model}}', CamelCase::convertToCamelCase($relationship->relatedTable), $reverseRelationshipOriginalStub);
300
					$reverseRelationshipStub = str_replace('{{foreign_key}}', $relationship->foreignKey, $reverseRelationshipStub);
301
					$reverseRelationshipStub = str_replace('{{table_name}}', $relationship->tableName, $reverseRelationshipStub);
302
					$reverseRelationshipStub = str_replace('{{related_field}}', $relationship->relatedField, $reverseRelationshipStub);
303
					$reverseRelationshipStub = str_replace('{{foreign_table}}', CamelCase::pluralize(strtolower($relationship->relatedTable)), $reverseRelationshipStub);
304
				}
305
				else {
306
					$reverseRelationshipOriginalStub = File::get($this->stubsDirectory . '/Model/ModelReverseRelationship.php');
307
					$reverseRelationshipStub = str_replace('{{foreign_model}}', $relationship->modelName, $reverseRelationshipOriginalStub);
308
					$reverseRelationshipStub = str_replace('{{field}}', $relationship->foreignKey, $reverseRelationshipStub);
309
					$reverseRelationshipStub = str_replace('{{foreign_field}}', $relationship->localKey, $reverseRelationshipStub);
310
					$reverseRelationshipStub = str_replace('{{type}}', $relationship->type, $reverseRelationshipStub);
311
					$reverseRelationshipStub = str_replace('{{foreign_table}}', $functionName, $reverseRelationshipStub);
312
				}
313
					
314
				$reverseRelationshipStub = str_replace('{{model_namespace}}', $this->scaffolderConfig->generator->namespaces->models, $reverseRelationshipStub);
315
				
316
				$functions .= $reverseRelationshipStub ;
317
318 View Code Duplication
				if(isset($relationship->foreignKey->eager) && $relationship->foreignKey->eager){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
319
					array_push($eagerArray, "'".$relationship->foreignKey->table."'");
320
				}
321
			}
322
323
			
324
		}
325
326
		$this->stub = str_replace('{{reverseRelationship}}', $functions, $this->stub);
327
328
329
		return $this;
330
	}
331
332
333
	/**
334
	 * Replace eager code for each foreing key with eager = true 
335
	 *
336
	 * @return $this
337
	 */
338 View Code Duplication
	private function replaceEagerCode()
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...
339
	{
340
		$storeCommands = $updateCommands = $ruleCommands = $useCommands = '';
341
		$eagerConditions = $eagerJoins = '';
342
343
		$storeEagerStubOriginal = File::get($this->stubsDirectory . 'StoreEager.php');
344
		$updateEagerStubOriginal = File::get($this->stubsDirectory . 'UpdateEager.php');
345
		$rulesEagerStubOriginal = File::get($this->stubsDirectory . 'RulesEager.php');
346
		$useEagerStubOriginal = File::get($this->stubsDirectory . 'UseEager.php');
347
		$joinEagerStubOriginal = File::get($this->stubsDirectory . 'SearchConditions/JoinEager.php');
348
349
		foreach ($this->modelData->fields as $field)
350
		{
351
			
352
			// Check foreign key
353
			if ($field->foreignKey && isset($field->foreignKey->eager) && $field->foreignKey->eager)
354
			{
355
356
				$storeCommands 	.= str_replace('{{foreign_model_name}}', CamelCase::convertToCamelCase($field->foreignKey->table), $this->replaceForeingStrings($field, $storeEagerStubOriginal));
357
				$updateCommands	.= str_replace('{{foreign_model_name}}', CamelCase::convertToCamelCase($field->foreignKey->table), $this->replaceForeingStrings($field, $updateEagerStubOriginal)) ;
358
				$ruleCommands	.= str_replace('{{foreign_model_name}}', CamelCase::convertToCamelCase($field->foreignKey->table), $this->replaceForeingStrings($field, $rulesEagerStubOriginal)) ;
359
				$useCommands	.= str_replace('{{foreign_model_name}}', CamelCase::convertToCamelCase($field->foreignKey->table), $this->replaceForeingStrings($field, $useEagerStubOriginal)) ;
360
				$eagerJoins		.= $this->replaceForeingStrings($field, $joinEagerStubOriginal) ;
361
362
				// search eager fields
363
				$foreignModelData = $this->getModelData($field->foreignKey->table);
364
				$foreignControllerCompiler = new ControllerCompiler($this->scaffolderConfig, $foreignModelData);
365
				$foreignControllerCompiler->setEagerTable($this->modelData->tableName);
0 ignored issues
show
Bug introduced by
The method setEagerTable() cannot be called from this context as it is declared protected in class Scaffolder\Compilers\AbstractCompiler.

This check looks for access to methods that are not accessible from the current context.

If you need to make a method accessible to another context you can raise its visibility level in the defining class.

Loading history...
366
				$eagerConditions 	.= $foreignControllerCompiler->getSearchConditions();
367
				$eagerUniqueRules = $foreignControllerCompiler->getEagerUniqueRules();
368
				$eagerUniqueRules = str_replace("{{class_name_lw}}", strtolower($this->modelName), $eagerUniqueRules);
369
				$eagerUniqueRules = str_replace("{{field}}", $field->name, $eagerUniqueRules);
370
				$ruleCommands = str_replace('{{unique_eager_rules}}', $eagerUniqueRules, $ruleCommands) ;
371
			}
372
373
		}
374
375
		$this->stub = str_replace('{{store_eager_objects}}', $storeCommands, $this->stub);
376
		$this->stub = str_replace('{{update_eager_objects}}', $updateCommands, $this->stub);
377
		$this->stub = str_replace('{{rules_eager}}', $ruleCommands, $this->stub);
378
		$this->stub = str_replace('{{eager_use_classes}}', $useCommands, $this->stub);
379
		$this->stub = str_replace('{{eager_joins}}', $eagerJoins, $this->stub);
380
		$this->stub = str_replace('{{eager_conditions}}', $eagerConditions, $this->stub);
381
		$this->stub = str_replace('{{eager_table}}', $this->eagerTable, $this->stub);
382
		
383
384
385
		return $this;
386
	}
387
388
	/**
389
	 * replace relationship tables
390
	 *
391
	 * @return $this
392
	 */
393 View Code Duplication
	public function replaceRelationshipTables() {
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...
394
395
		$functions = "";
396
		$functionsCall = "";
397
		$removeAll = "";
398
		$removeAllCall = "";
399
		$includes = "";
400
		$joins = "";
401
		$joinSorts = "";
0 ignored issues
show
Unused Code introduced by
$joinSorts 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...
402
403
		$method = File::get($this->stubsDirectory . '/Model/ModelRelationshipTable.php');
404
405
		foreach ($this->modelData->reverseRelationships as $relationship) {
406
407
			if ($relationship->type == "belongsToMany") {
408
				$relatedTablePluralized = CamelCase::pluralize($relationship->relatedTable);
409
				$relatedTablePluralizedUc = CamelCase::pluralize(CamelCase::convertToCamelCase($relationship->relatedTable));
410
411
				$replacedMethod = '';
0 ignored issues
show
Unused Code introduced by
$replacedMethod 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...
412
				$replacedMethod = str_replace('{{related_table_pl_uc}}', $relatedTablePluralizedUc, $method);
413
				$replacedMethod = str_replace('{{class_name_lw}}', $this->modelData->tableName, $replacedMethod);
414
				$replacedMethod = str_replace('{{related_table_pl}}', $relatedTablePluralized, $replacedMethod);
415
				$replacedMethod = str_replace('{{foreign_key}}', $relationship->foreignKey, $replacedMethod);
416
				$replacedMethod = str_replace('{{related_field}}', $relationship->relatedField, $replacedMethod);
417
				$replacedMethod = str_replace('{{foreign_table_lw}}', strtolower($relationship->modelName), $replacedMethod);
418
				$replacedMethod = str_replace('{{foreign_table}}', $relationship->modelName, $replacedMethod);
419
420
				$functions .= $replacedMethod;
421
422
				$methodCall = 'if (array_key_exists(\'{{related_table_pl}}\', $vars))';
423
				$methodCall .= "\n\t\t\t";
424
				$methodCall .= '$this->save{{related_table_pl_uc}}($vars, ${{class_name_lw}});';
425
				$methodCall = str_replace('{{related_table_pl_uc}}', $relatedTablePluralizedUc, $methodCall);
426
				$methodCall = str_replace('{{related_table_pl}}', $relatedTablePluralized, $methodCall);
427
				$methodCall = str_replace('{{class_name_lw}}', $this->modelData->tableName, $methodCall);
428
429
				$functionsCall .= $methodCall . "\n\t\t";
430
				
431
				$removeAllMethod = File::get($this->stubsDirectory . '/Controller/ControllerRemoveAll.php');
432
				$removeAllMethod = str_replace('{{related_table_pl_uc}}', $relatedTablePluralizedUc, $removeAllMethod);
433
				$removeAllMethod = str_replace('{{foreign_key}}', $relationship->foreignKey, $removeAllMethod);
434
				$removeAllMethod = str_replace('{{foreign_table}}', $relationship->modelName, $removeAllMethod);
435
				$removeAllMethod = str_replace('{{foreign_table_lw_pl}}', CamelCase::pluralize(strtolower($relationship->modelName)), $removeAllMethod);
436
				
437
				$removeAll .= $removeAllMethod;
438
439
				$removeAllCallMethod = '$this->deleteAll{{related_table_pl_uc}}(${{class_name_lw}}[\'id\']);';
440
				$removeAllCallMethod = str_replace('{{related_table_pl_uc}}', $relatedTablePluralizedUc, $removeAllCallMethod);
441
				$removeAllCallMethod = str_replace('{{class_name_lw}}', $this->modelData->tableName, $removeAllCallMethod);
442
				
443
				$removeAllCall .= $removeAllCallMethod . "\n\t\t";
444
445
				$joinRelationshipTableStub = File::get($this->stubsDirectory . 'SearchConditions/joinRelationshipTable.php');
446
				$joinRelationshipTableStub = str_replace('{{class_name_lw}}', $this->modelData->tableName, $joinRelationshipTableStub);
447
				$joinRelationshipTableStub = str_replace('{{related_table_pl}}', $relatedTablePluralized, $joinRelationshipTableStub);
448
				$joinRelationshipTableStub = str_replace('{{related_table}}', CamelCase::convertToCamelCase($relationship->relatedTable), $joinRelationshipTableStub);
449
				$joinRelationshipTableStub = str_replace('{{foreign_key}}', $relationship->foreignKey, $joinRelationshipTableStub);
450
				$joinRelationshipTableStub = str_replace('{{related_field}}', $relationship->relatedField, $joinRelationshipTableStub);
451
				$joinRelationshipTableStub = str_replace('{{foreign_table}}', $relationship->tableName, $joinRelationshipTableStub);
452
453
				$joins .= $joinRelationshipTableStub . "\n";
454
455
				$use = 'use App\Models\{{foreign_table}};';
456
				$use = str_replace('{{foreign_table}}', $relationship->modelName, $use);
457
458
				$includes .= $use . "\n";
459
			}
460
		}
461
462
		$this->stub = str_replace('{{relationship_tables_store}}', $functions, $this->stub);
463
464
		$this->stub = str_replace('{{relationship_tables_call}}', $functionsCall, $this->stub);
465
466
		$this->stub = str_replace('{{remove_relationship_objects}}', $removeAll, $this->stub);
467
468
		$this->stub = str_replace('{{remove_relationship_objects_call}}', $removeAllCall, $this->stub);
469
470
		$this->stub = str_replace('{{relationship_tables_classes}}', $includes, $this->stub);
471
472
		$this->stub = str_replace('{{relationship_tables_joins}}', $joins, $this->stub);
473
474
		
475
		
476
		return $this;
477
478
	}
479
480
481
	/**
482
	 * Replace search conditions
483
	 *
484
	 * @return $this
485
	 */
486
	private function replaceSearchConditions(){
487
488
		$searchConditions = $this->getSearchConditions();
489
490
		$this->stub = str_replace('{{conditions}}', $searchConditions, $this->stub);
491
492
		return $this;
493
	}
494
495
	/**
496
	 * get search conditions
497
	 *
498
	 * @return $this
499
	 */
500 View Code Duplication
	public function getSearchConditions(){
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...
501
502
		$fieldConditions = '';
503
504
		$searchConditions = File::get($this->stubsDirectory . '/SearchConditions/Conditions.php');
505
506
		foreach ($this->modelData->fields as $field)
507
		{
508
509
			$fieldConditions .= $this->replaceFieldStrings($field, $this->getConditionStubByField($field)) ;
510
511
		}
512
513
		// replace all field conditions
514
		$searchConditions = str_replace('{{field_conditions}}', $fieldConditions, $searchConditions);
515
516
		// replace table name
517
		$searchConditions = str_replace('{{table_name}}', $this->modelData->tableName, $searchConditions);
518
519
		return $searchConditions ;
520
521
	}
522
523
	/**
524
	 * get search conditions stub by db type
525
	 *
526
	 * @param string $field
527
	 *
528
	 * @return $this
529
	 */
530
	private $conditionsStub = [];
531 View Code Duplication
	private function getConditionStubByField($field){
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...
532
		
533
		if($field->index == 'primary'){
534
			$dbType = 'primary' ;
535
		}
536
		elseif($field->foreignKey){
537
			$dbType = 'primary' ;
538
		}
539
		elseif($field->type->db == 'enum'){
540
			$dbType = 'primary' ;
541
		}
542
		elseif($field->type->db == 'boolean'){
543
			$dbType = 'primary' ;
544
		}
545
		elseif($field->type->db == 'text'){
546
			$dbType = 'string' ;
547
		}
548
		else {
549
			$dbType = $field->type->db ;
550
		}
551
552
		if(array_key_exists($dbType, $this->conditionsStub)){
553
			return $this->conditionsStub[$dbType];
554
		}
555
		else {
556
			$this->conditionsStub[$dbType] = File::get($this->stubsDirectory . 'SearchConditions/'. ucwords($dbType). '.php');;
557
558
			return $this->conditionsStub[$dbType];
559
		}
560
	}
561
562 View Code Duplication
	public function replaceSortConditions()	{
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...
563
		$joinSorts = '';
564
565
		foreach ($this->modelData->fields as $field) {
566
			if($field->foreignKey){
567
				$joinSortStub = File::get($this->stubsDirectory . 'SearchConditions/JoinSort.php');
568
				$joinSortStub = str_replace('{{field}}', $field->name, $joinSortStub);
569
				$joinSortStub = str_replace('{{foreign_table}}', $field->foreignKey->table, $joinSortStub);
570
				$joinSortStub = str_replace('{{foreign_key}}', $field->foreignKey->table, $joinSortStub);
571
				$joinSorts .= $joinSortStub;
572
573
			}
574
			
575
	
576
			
577
		}
578
		
579
580
		$this->stub = str_replace('{{relationship_tables_joins_sort}}', $joinSorts, $this->stub);
581
582
		return $this;
583
	}
584
585
586
587
	/**
588
	 * replace reverse relationships
589
	 *
590
	 * @return $this
591
	 */
592 View Code Duplication
	public function replaceReverseRelationshipsFunctions(){
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...
593
594
		$functions = '';
595
596
		$method = File::get($this->stubsDirectory . '/Model/ModelReverseRelationshipFunctions.php');
597
598
		foreach ($this->modelData->reverseRelationships as $relationship)
599
		{
600
			$functionName = '';
0 ignored issues
show
Unused Code introduced by
$functionName 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...
601
			if ($relationship->type == "hasOne")
602
				$functionName = strtolower($relationship->modelName);
603
			elseif ($relationship->type == "belongsToMany") 
604
				$functionName = CamelCase::pluralize(strtolower($relationship->relatedTable));
605
			else 
606
				$functionName = CamelCase::pluralize(strtolower($relationship->modelName));
607
608
			$replacedMethod = '';
0 ignored issues
show
Unused Code introduced by
$replacedMethod 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...
609
			$replacedMethod = str_replace('{{function_name}}', $functionName, $method);
610
			$replacedMethod = str_replace('{{class_name_lw}}', $this->modelData->tableName, $replacedMethod);
611
			$replacedMethod = str_replace('{{class_name}}', ucwords($this->modelData->tableName), $replacedMethod);
612
613
			$functions .= $replacedMethod;
614
		}
615
616
		$this->stub = str_replace('{{reverseRelationshipFunctions}}', $functions, $this->stub);
617
618
		return $this;
619
620
	}
621
622
623
	/**
624
	 * replace checkbox fields
625
	 *
626
	 * @return $this
627
	 */
628 View Code Duplication
	public function replaceCheckbox(){
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...
629
630
		$method = File::get($this->stubsDirectory . '/Model/ModelCheckbox.php');
631
		$key = false;
0 ignored issues
show
Unused Code introduced by
$key 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...
632
633
		$method = str_replace('{{class_name_lw}}', $this->modelData->tableName, $method);
634
		$method = str_replace('{{class_name}}', ucwords($this->modelData->tableName), $method);
635
		$method = str_replace('{{model_name}}', $this->modelData->modelName, $method);
636
		$this->stub = str_replace('{{checkbox}}', $method, $this->stub);
637
638
		return $this;
639
640
	}
641
642
643
	/**
644
	 * Replace simple filter
645
	 *
646
	 * @return $this
647
	 */
648 View Code Duplication
	private function replaceSimpleFilter(){
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...
649
		$i = 0;
0 ignored issues
show
Unused Code introduced by
$i 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...
650
651
		$stubSimpleFilter = '';
652
653
		foreach ($this->modelData->fields as $field)
654
		{
655
			//var_dump($field->name);
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
656
			
657
			if($field->index == 'primary'){
658
				$dbType = 'primaryKey' ;
659
			}
660
			elseif($field->foreignKey){
661
				$dbType = 'primary' ;
662
			}
663
			elseif($field->type->db == 'enum'){
664
				$dbType = 'primary' ;
665
			}
666
			elseif($field->type->db == 'boolean'){
667
				$dbType = 'primary' ;
668
			}
669
			elseif($field->type->db == 'text'){
670
				$dbType = 'string' ;
671
			}
672
			else {
673
				$dbType = $field->type->db ;
674
			}
675
			
676
			if($dbType == 'primaryKey')
677
			{
678
				$stubSimpleFilter .= '$query->where("'.$this->modelData->tableName.'.'.$field->name.'", "=", $'.$this->modelData->tableName.'Conditions["'.$field->name.'"])'.PHP_EOL;
679
			}
680
681
			if($dbType == 'primary')
682
			{
683
				$stubSimpleFilter .= '->orWhere("'.$this->modelData->tableName.'.'.$field->name.'", "=", $'.$this->modelData->tableName.'Conditions["'.$field->name.'"])'.PHP_EOL;
684
			}
685
686
			if($dbType == 'string')
687
			{
688
				$stubSimpleFilter .= '->orWhere("'.$this->modelData->tableName.'.'.$field->name.'", "LIKE", "%".$'.$this->modelData->tableName.'Conditions["'.$field->name.'"]."%")'.PHP_EOL;
689
			}
690
691
			if($dbType == 'date' || $dbType == 'datetime' || $dbType == 'float' || $dbType == 'integer' || $dbType == 'number')
692
			{
693
				$stubSimpleFilter .= '->orWhere("'.$this->modelData->tableName.'.'.$field->name.'", "=", $'.$this->modelData->tableName.'Conditions["'.$field->name.'"])'.PHP_EOL;
694
			}
695
696
		}
697
		$stubSimpleFilter .= ';';
698
		$this->stub = str_replace('{{simple_filter}}', $stubSimpleFilter, $this->stub);
699
700
		return $this;
701
	}
702
}