Completed
Push — master ( dc322e...438d0e )
by Mahmoud
03:27
created

SeederLoaderTrait::findSeedersClasses()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 24
Code Lines 10

Duplication

Lines 16
Ratio 66.67 %

Importance

Changes 0
Metric Value
dl 16
loc 24
rs 8.5125
c 0
b 0
f 0
cc 5
eloc 10
nc 5
nop 2
1
<?php
2
3
namespace App\Ship\Engine\Loaders;
4
5
use App\Ship\Engine\Butlers\Facades\LoaderButler;
6
use File;
7
use Illuminate\Support\Collection;
8
9
/**
10
 * Class SeederLoaderTrait.
11
 *
12
 * This Class has inverted dependency :( you must extend this class from the default
13
 * seeder class provided by the framework (database/seeds/DatabaseSeeder.php)
14
 *
15
 * @author  Mahmoud Zalt <[email protected]>
16
 */
17
trait SeederLoaderTrait
18
{
19
20
    /**
21
     * Default seeders directory for containers and port
22
     *
23
     * @var  string
24
     */
25
    protected $seedersPath = '/Data/Seeders';
26
27
    /**
28
     * runLoadingSeeders
29
     */
30
    public function runLoadingSeeders()
31
    {
32
        $this->loadSeedersFromContainers();
33
        $this->loadSeedersFromShip();
34
    }
35
36
    /**
37
     * loadSeedersFromContainers
38
     */
39 View Code Duplication
    private function loadSeedersFromContainers()
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...
40
    {
41
        $seedersClasses = new Collection();
42
43
        foreach (LoaderButler::getContainersNames() as $containerName) {
44
45
            $containersDirectories[] = base_path('app/Containers/' . $containerName . $this->seedersPath);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$containersDirectories was never initialized. Although not strictly required by PHP, it is generally a good practice to add $containersDirectories = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
46
47
        }
48
49
        $seedersClasses = $this->findSeedersClasses($containersDirectories, $seedersClasses);
0 ignored issues
show
Bug introduced by
The variable $containersDirectories does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
50
        $orderedSeederClasses = $this->sortSeeders($seedersClasses);
51
52
        $this->loadSeeders($orderedSeederClasses);
53
    }
54
55
    /**
56
     * loadSeedersFromShip
57
     */
58 View Code Duplication
    private function loadSeedersFromShip()
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...
59
    {
60
        $seedersClasses = new Collection();
61
62
        // it has to do it's own loop for now
63
        foreach (LoaderButler::getShipFoldersNames() as $portFolderName) {
64
65
            // TODO: Currently only the Tests Seeder will work since this is statically defined.
66
            // Need to Loop over that Directory and load the any Seeder file there.
67
            $containersDirectories[] = base_path('app/Ship/Features/Seeders/Tests');
0 ignored issues
show
Coding Style Comprehensibility introduced by
$containersDirectories was never initialized. Although not strictly required by PHP, it is generally a good practice to add $containersDirectories = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
68
        }
69
70
        $seedersClasses = $this->findSeedersClasses($containersDirectories, $seedersClasses);
0 ignored issues
show
Bug introduced by
The variable $containersDirectories does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
71
        $orderedSeederClasses = $this->sortSeeders($seedersClasses);
72
73
        $this->loadSeeders($orderedSeederClasses);
74
    }
75
76
    /**
77
     * @param array $directories
78
     * @param       $seedersClasses
79
     *
80
     * @return  mixed
81
     */
82
    private function findSeedersClasses(array $directories, $seedersClasses)
83
    {
84
        foreach ($directories as $directory) {
85
86 View Code Duplication
            if (File::isDirectory($directory)) {
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...
87
88
                $files = File::allFiles($directory);
89
90
                foreach ($files as $seederClass) {
91
92
                    if (File::isFile($seederClass)) {
93
94
                        // do not seed the classes now, just store them in a collection and w
95
                        $seedersClasses->push(
96
                            LoaderButler::getClassFullNameFromFile(
97
                                $seederClass->getPathname())
98
                        );
99
                    }
100
                }
101
            }
102
        }
103
104
        return $seedersClasses;
105
    }
106
107
    /**
108
     * @param $seedersClasses
109
     *
110
     * @return  \Illuminate\Support\Collection|static
111
     */
112
    private function sortSeeders($seedersClasses)
113
    {
114
        $orderedSeederClasses = new Collection();
115
116
        if (!$seedersClasses->isEmpty()) {
117
118
            foreach ($seedersClasses as $key => $seederFullClassName) {
119
                // if the class full namespace contain "_" it means it needs to be seeded in order
120
                if (preg_match('/_/', $seederFullClassName)) {
121
                    // move all the seeder classes that needs to be seeded in order to their own Collection
122
                    $orderedSeederClasses->push($seederFullClassName);
123
                    // delete the moved classes from the original collection
124
                    $seedersClasses->forget($key);
125
                }
126
            }
127
128
            // sort the classes that needed to be ordered
129
            $orderedSeederClasses = $orderedSeederClasses->sortBy(function ($seederFullClassName) {
130
                // get the order number form the end of each class name
131
                $orderNumber = substr($seederFullClassName, strpos($seederFullClassName, "_") + 1);
132
133
                return $orderNumber;
134
            });
135
136
            // append the randomly ordered seeder classes to the end of the ordered seeder classes
137
            foreach ($seedersClasses as $seederClass) {
138
                $orderedSeederClasses->push($seederClass);
139
            }
140
141
            return $orderedSeederClasses;
142
        }
143
144
    }
145
146
    /**
147
     * @param $seedersClasses
148
     */
149
    private function loadSeeders($seedersClasses)
150
    {
151
        foreach ($seedersClasses as $seeder) {
152
            // seed it with call
153
            $this->call($seeder);
0 ignored issues
show
Bug introduced by
It seems like call() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
154
        }
155
    }
156
157
}
158