MigrationCompiler::addFields()   C
last analyzed

Complexity

Conditions 17
Paths 56

Size

Total Lines 80
Code Lines 38

Duplication

Lines 5
Ratio 6.25 %

Importance

Changes 0
Metric Value
dl 5
loc 80
rs 5.033
c 0
b 0
f 0
cc 17
eloc 38
nc 56
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Scaffolder\Compilers\Core;
4
5
use Carbon\Carbon;
6
use Illuminate\Support\Facades\File;
7
use Scaffolder\Compilers\AbstractCompiler;
8
use Scaffolder\Compilers\Support\FileToCompile;
9
use Scaffolder\Compilers\Support\PathParser;
10
11
class MigrationCompiler extends AbstractCompiler
12
{
13
	private $date;
14
15
	protected $cachePrefix 	= 'migration_';
16
	protected $stubFilename = 'Migration.php' ;
17
18
	public function __construct($scaffolderConfig, $modelData = null)
19
	{
20
		$this->stubsDirectory = __DIR__ . '/../../../../stubs/Api/';
21
22
		parent::__construct($scaffolderConfig, $modelData);
23
24
		$this->date = Carbon::now();
25
	}
26
27
	/**
28
	 * Replace and store the Stub.
29
	 *
30
	 * @return string
31
	 */
32
	public function replaceAndStore()
33
	{
34
		
35
		return $this->addFields()
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->addFields(...modelData->modelHash)); (Scaffolder\Compilers\Core\MigrationCompiler) 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...
36
					->store(new FileToCompile(false, $this->modelData->modelHash));
37
		
38
	}
39
40
	/**
41
	 * Get output filename
42
	 *
43
	 *
44
	 * @return $this
45
	 */
46
	protected function getOutputFilename()
47
	{
48
49
		return  PathParser::parse($this->scaffolderConfig->generator->paths->migrations) . $this->date->format('Y_m_d_') . str_pad($this->modelData->migrationOrder, 2, 0, STR_PAD_LEFT) . '_create_' . strtolower($this->modelName) . '_table.php';
0 ignored issues
show
Bug Best Practice introduced by
The return type of return \Scaffolder\Compi...elName) . '_table.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...
50
	}
51
52
	/**
53
	 * Add fields.
54
	 *
55
	 * @param $modelData
56
	 *
57
	 * @return $this
58
	 */
59
	private function addFields()
60
	{
61
		// Default primary key
62
		$fields = "\t\t\t\$table->increments('id');" . PHP_EOL . PHP_EOL;
63
64
		// Check primary key
65
		# TODO FIX, primary
66
		
67
		foreach ($this->modelData->fields as $field)
68
		{
69
			$parsedModifiers = '';
70
71
			if($field->index == "primary")
72
				continue ;
73
			if($this->modelData->timeStamps && $field->name == "created_at")
74
				continue ;
75
			if($this->modelData->timeStamps && $field->name == "updated_at")
76
				continue ;
77
78
			// Check modifiers
79
			if (!empty($field->modifiers))
80
			{
81
				$modifiersArray = explode(':', $field->modifiers);
82
83
				foreach ($modifiersArray as $modifier)
84
				{
85
					$modifierAndValue = explode(',', $modifier);
86
87
					if (count($modifierAndValue) == 2)
88
					{
89
						$parsedModifiers .= '->' . $modifierAndValue[0] . '(' . $modifierAndValue[1] . ')';
90
					}
91
					else
92
					{
93
						$parsedModifiers .= '->' . $modifierAndValue[0] . '()';
94
					}
95
				}
96
			}
97
98
			// Check foreign key for unsigned modifier
99
			if ($field->foreignKey)
100
			{
101
				$parsedModifiers .= '->unsigned()';
102
			}
103
104
			// Check indexes
105
			if ($field->index != 'none')
106
			{
107
				$fields .= sprintf("\t\t\t\$table->%s('%s')%s->%s();" . PHP_EOL, $field->type->db, $field->name, $parsedModifiers, $field->index);
108
			}
109
			else
110
			{
111
				if ($field->type->db == "enum") {
112
					$items = '';
113 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...
114
						$items .= "'" . $option . "'";
115
						if ($key < (count($field->options) - 1))
116
							$items .= ", ";
117
					}
118
119
					$fields .= sprintf("\t\t\t\$table->%s('%s', array(%s));" . PHP_EOL, $field->type->db, $field->name, $items);
120
				}
121
				else
122
					$fields .= sprintf("\t\t\t\$table->%s('%s')%s;" . PHP_EOL, $field->type->db, $field->name, $parsedModifiers);
123
			}
124
125
			// Check foreign key
126
			if ($field->foreignKey)
127
			{
128
				$fields .= sprintf("\t\t\t\$table->foreign('%s')->references('%s')->on('%s');" . PHP_EOL . PHP_EOL, $field->name, $field->foreignKey->field, $field->foreignKey->table);
129
			}
130
		}
131
132
		if($this->modelData->timeStamps)
133
			$fields .= PHP_EOL . "\t\t\t\$table->timestamps();" . PHP_EOL;
134
135
		$this->stub = str_replace('{{fields}}', $fields, $this->stub);
136
137
		return $this;
138
	}
139
}