Passed
Push — master ( c1bd78...130d27 )
by Jesús
01:50
created

MakeRepositoryCommand::handle()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 37
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 18
nc 4
nop 0
dl 0
loc 37
rs 8.5806
c 0
b 0
f 0
1
<?php
2
3
namespace OkayBueno\Repositories\Commands;
4
5
/**
6
 * Class MakeRepositoryCommand
7
 * @package OkayBueno\Repositories\Commands
8
 */
9
class MakeRepositoryCommand extends MakeBaseCommand
10
{
11
    protected $signature = 'make:repository {model} {--implementation=}';
12
    protected $description = 'Create a new repository for the given model. This will create a repository interface, the implementation for Eloquent and will inject the model on it.';
13
    
14
    private $implementation;
15
    private $modelClassShortName;
16
    private $modelClassNamespace;
17
    private $repositoryInterfaceName;
18
    private $repositoryInterfaceNamespace;
19
    private $repositoryClassName;
20
    private $repositoryClassNamespace;
21
    
22
    
23
    /**
24
     * Execute the console command.
25
     *
26
     * @return mixed
27
     */
28
    public function handle()
29
    {
30
        $model = $this->argument('model');
31
        $implementation = strtolower( $this->option('implementation') );
32
        
33
        if ( class_exists( $model ) )
0 ignored issues
show
Bug introduced by
It seems like $model can also be of type array; however, parameter $class_name of class_exists() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

33
        if ( class_exists( /** @scrutinizer ignore-type */ $model ) )
Loading history...
34
        {
35
            $supportedImplementations = array_keys( config( 'repositories.supported_implementations' ) );
0 ignored issues
show
Bug introduced by
The function config was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

35
            $supportedImplementations = array_keys( /** @scrutinizer ignore-call */ config( 'repositories.supported_implementations' ) );
Loading history...
36
            
37
            if ( $implementation )
38
            {
39
                if ( !in_array( $implementation, $supportedImplementations ) )
40
                {
41
                    $this->error("The implementation '$implementation' is not supported at this moment. Want me to provide support? Open an issue :).");
42
                    
43
                    return FALSE;
44
                }
45
            } else
46
            {
47
                $implementation = $this->findDefaultImplementation();
48
            }
49
            
50
            // Populate the properties with the right values.
51
            $this->populateValuesForProperties( $model, $implementation );
52
            
53
            $this->createInterface();
54
            $this->createRepository();
55
            
56
            $this->info('Generating autoload...');
57
            $this->composer->dumpAutoloads();
58
            $this->info('Done!');
59
            
60
            return true;
61
            
62
        }
63
        
64
        $this->error( "The '$model' model does not exist. Please check that the namespace and the class name are valid.");
65
        
66
    }
67
    
68
    /**
69
     * @param $model
70
     * @param $implementation
71
     */
72
    protected function populateValuesForProperties( $model, $implementation )
73
    {
74
        $modelClass = new \ReflectionClass( $model );
75
        
76
        $this->implementation = $implementation;
77
        
78
        $this->modelClassShortName = $modelClass->getShortName();
79
        $this->modelClassNamespace = $modelClass->getNamespaceName();
80
        
81
        $this->repositoryClassName = $this->modelClassShortName.'Repository';
82
        $this->repositoryInterfaceName = $this->repositoryClassName.'Interface';
83
        
84
        $this->repositoryInterfaceNamespace = rtrim( config( 'repositories.repository_interfaces_namespace' ), '\\' );
0 ignored issues
show
Bug introduced by
The function config was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

84
        $this->repositoryInterfaceNamespace = rtrim( /** @scrutinizer ignore-call */ config( 'repositories.repository_interfaces_namespace' ), '\\' );
Loading history...
85
        $this->repositoryClassNamespace = $this->repositoryInterfaceNamespace.'\\'.ucfirst( $implementation );
86
    }
87
    
88
    /**
89
     *
90
     */
91
    protected function createRepository()
92
    {
93
        $basePath = config( 'repositories.repositories_path' ).'/'.ucfirst( $this->implementation );
0 ignored issues
show
Bug introduced by
The function config was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

93
        $basePath = /** @scrutinizer ignore-call */ config( 'repositories.repositories_path' ).'/'.ucfirst( $this->implementation );
Loading history...
94
        
95
        $classFilePath = $basePath.'/'.$this->repositoryClassName.'.php';
96
        
97
        $this->makeDirectory( $basePath );
98
        
99 View Code Duplication
        if ( !$this->filesystem->exists( $classFilePath ) )
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...
100
        {
101
            // Read the stub and replace
102
            $this->filesystem->put( $classFilePath, $this->compileRepositoryStub() );
103
            $this->info("'".ucfirst( $this->implementation )."' implementation created successfully for '$this->modelClassShortName'.");
104
            $this->composer->dumpAutoloads();
105
        } else
106
        {
107
            $this->error("The repository '$classFilePath' already exists, so it was skipped.");
108
        }
109
    }
110
    
111
    
112
    /**
113
     *
114
     */
115
    protected function createInterface()
116
    {
117
        $repositoriesBasePath = config( 'repositories.repositories_path' );
0 ignored issues
show
Bug introduced by
The function config was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

117
        $repositoriesBasePath = /** @scrutinizer ignore-call */ config( 'repositories.repositories_path' );
Loading history...
118
        
119
        $interfaceFilePath = $repositoriesBasePath.'/'.$this->repositoryInterfaceName.'.php';
120
        
121
        $this->makeDirectory( $repositoriesBasePath );
122
        
123 View Code Duplication
        if ( !$this->filesystem->exists( $interfaceFilePath ) )
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...
124
        {
125
            // Read the stub and replace
126
            $this->filesystem->put( $interfaceFilePath, $this->compileRepositoryInterfaceStub() );
0 ignored issues
show
Bug introduced by
It seems like $this->compileRepositoryInterfaceStub() can also be of type OkayBueno\Repositories\C...s\MakeRepositoryCommand; however, parameter $contents of Illuminate\Filesystem\Filesystem::put() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

126
            $this->filesystem->put( $interfaceFilePath, /** @scrutinizer ignore-type */ $this->compileRepositoryInterfaceStub() );
Loading history...
127
            $this->info("Interface created successfully for '$this->modelClassShortName'.");
128
            $this->composer->dumpAutoloads();
129
        } else
130
        {
131
            $this->error("The interface '$this->repositoryInterfaceName' already exists, so it was skipped.");
132
        }
133
    }
134
    
135
    
136
    /**
137
     * @return MakeRepositoryCommand|string
138
     */
139
    protected function compileRepositoryInterfaceStub()
140
    {
141
        $stub = $this->filesystem->get(__DIR__ . '/../stubs/repository-interface.stub');
142
        
143
        $stub = $this->replaceInterfaceNamespace( $stub );
144
        $stub = $this->replaceInterfaceName( $stub );
145
        
146
        return $stub;
147
    }
148
    
149
    /**
150
     * @return mixed|MakeRepositoryCommand|string
151
     */
152
    protected function compileRepositoryStub()
153
    {
154
        $stub = $this->filesystem->get(__DIR__ . '/../stubs/repository.stub');
155
        
156
        $stub = $this->replaceInterfaceNamespace( $stub );
157
        $stub = $this->replaceInterfaceName( $stub );
158
        $stub = $this->replaceParentRepositoryClassNamespaceAndName( $stub );
159
        $stub = $this->replaceRepositoryClassNamespaceAndName( $stub );
160
        $stub = $this->replaceModelClassNamespaceAndName( $stub );
161
        
162
        return $stub;
163
    }
164
    
165
    /**
166
     * @param $stub
167
     * @return $this
168
     */
169
    private function replaceInterfaceNamespace( $stub )
170
    {
171
        return str_replace('{{repositoryInterfaceNamespace}}', $this->repositoryInterfaceNamespace, $stub);
172
    }
173
    
174
    /**
175
     * @param $stub
176
     * @return mixed
177
     */
178
    private function replaceInterfaceName( $stub )
179
    {
180
        return str_replace('{{repositoryInterfaceName}}', $this->repositoryInterfaceName, $stub);
181
    }
182
    
183
    
184
    /**
185
     * @param $stub
186
     * @return mixed
187
     */
188
    private function replaceParentRepositoryClassNamespaceAndName( $stub )
189
    {
190
        $implementations = config( 'repositories.supported_implementations' );
0 ignored issues
show
Bug introduced by
The function config was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

190
        $implementations = /** @scrutinizer ignore-call */ config( 'repositories.supported_implementations' );
Loading history...
191
        
192
        $parentClassImplementation = $implementations[ $this->implementation ];
193
        
194
        $reflex = new \ReflectionClass($parentClassImplementation);
195
        
196
        $stub = str_replace('{{parentRepositoryClassNamespace}}', $reflex->getNamespaceName(), $stub);
197
        
198
        return str_replace('{{parentRepositoryClassName}}', $reflex->getShortName(), $stub);
199
    }
200
    
201
    /**
202
     * @param $stub
203
     * @return mixed
204
     */
205
    private function replaceRepositoryClassNamespaceAndName( $stub )
206
    {
207
        $stub = str_replace('{{repositoryClassName}}', $this->repositoryClassName, $stub);
208
        
209
        return str_replace('{{repositoryClassNamespace}}', $this->repositoryClassNamespace, $stub);
210
    }
211
    
212
    
213
    /**
214
     * @param $stub
215
     * @return mixed
216
     */
217
    private function replaceModelClassNamespaceAndName( $stub )
218
    {
219
        $stub = str_replace('{{modelName}}', $this->modelClassShortName, $stub);
220
        
221
        return  str_replace('{{modelNamespace}}', $this->modelClassNamespace, $stub);
222
    }
223
    
224
}