Passed
Push — feat/rename-capsules ( 90f7bc...70a051 )
by Quentin
10:10 queued 04:02
created

CapsuleRename::replaceInFile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 3
rs 10
1
<?php
2
3
namespace A17\Twill\Commands;
4
5
use Illuminate\Console\Command;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, A17\Twill\Commands\Command. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
6
use Illuminate\Filesystem\Filesystem;
7
use Illuminate\Support\Str;
8
9
class CapsuleRename extends Command
10
{
11
    /**
12
     * The name and signature of the console command.
13
     *
14
     * @var string
15
     */
16
    protected $signature = 'twill:capsule:rename {currentName} {newName}';
17
18
    /**
19
     * The console command description.
20
     *
21
     * @var string
22
     */
23
    protected $description = 'Rename a Twill Capsule';
24
25
    /**
26
     * @var Filesystem
27
     */
28
    protected $filesystem;
29
30
    /**
31
     * @var string
32
     */
33
    protected $currentName;
34
35
    /**
36
     * @var string
37
     */
38
    protected $newName;
39
40
    /**
41
     * Create a new command instance.
42
     *
43
     * @return void
44
     */
45
    public function __construct(Filesystem $filesystem)
46
    {
47
        parent::__construct();
48
49
        $this->filesystem = $filesystem;
50
    }
51
52
    /**
53
     * Execute the console command.
54
     *
55
     * @return int
56
     */
57
    public function handle()
58
    {
59
        $this->currentName = Str::studly($this->argument('currentName'));
0 ignored issues
show
Bug introduced by
It seems like $this->argument('currentName') can also be of type array; however, parameter $value of Illuminate\Support\Str::studly() 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

59
        $this->currentName = Str::studly(/** @scrutinizer ignore-type */ $this->argument('currentName'));
Loading history...
60
        $this->newName = Str::studly($this->argument('newName'));
61
62
        $this->capsule = capsules($this->currentName);
0 ignored issues
show
Bug Best Practice introduced by
The property capsule does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
63
64
        if (!$this->capsule) {
65
            $this->error('Capsule not found');
66
67
            return Command::FAILURE;
68
        }
69
70
        $this->replaceFile('Controller', 'controllers_dir');
71
        $this->replaceFile('Request', 'requests_dir');
72
        $this->replaceFile('', 'models_dir');
73
        $this->replaceFile('Revision', 'models_dir');
74
        $this->replaceFile('Translation', 'models_dir');
75
        $this->replaceFile('Slug', 'models_dir');
76
        $this->replaceFile('Repository', 'repositories_dir');
77
78
        $this->replaceRoutes();
79
80
        $this->replaceSeeder();
81
82
        $this->generateMigration();
83
84
        $this->renameCapsuleDirectory();
85
86
        return Command::SUCCESS;
87
    }
88
89
    private function replaceFile($type, $directory)
90
    {
91
        $newFile = join([
0 ignored issues
show
Bug introduced by
The call to join() has too few arguments starting with array. ( Ignorable by Annotation )

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

91
        $newFile = /** @scrutinizer ignore-call */ join([

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
92
            $this->capsule[$directory],
93
            '/',
94
            Str::singular($this->newName),
95
            $type,
96
            '.php',
97
        ]);
98
99
        $this->filesystem->move(
100
            join([
101
                $this->capsule[$directory],
102
                '/',
103
                Str::singular($this->currentName),
104
                $type,
105
                '.php',
106
            ]),
107
            $newFile
108
        );
109
110
        $this->replaceInFile(
111
            $this->currentName,
112
            $this->newName,
113
            $newFile
114
        );
115
116
        $this->replaceInFile(
117
            Str::singular($this->currentName),
118
            Str::singular($this->newName),
119
            $newFile
120
        );
121
122
        $this->replaceInFile(
123
            lcfirst($this->currentName),
124
            lcfirst($this->newName),
125
            $newFile
126
        );
127
128
        $this->replaceInFile(
129
            strtolower(Str::snake(Str::singular($this->currentName))),
130
            strtolower(Str::snake(Str::singular($this->newName))),
131
            $newFile
132
        );
133
    }
134
135
    private function replaceRoutes()
136
    {
137
        $this->replaceInFile(
138
            lcfirst($this->currentName),
139
            lcfirst($this->newName),
140
            $this->capsule['routes_file']
141
        );
142
    }
143
144
    private function replaceSeeder()
145
    {
146
        $this->replaceInFile(
147
            $this->currentName,
148
            $this->newName,
149
            $this->capsule['seeds_psr4_path'] . '/DatabaseSeeder.php'
150
        );
151
    }
152
153
    private function generateMigration()
154
    {
155
        $table = strtolower(Str::snake($this->currentName));
156
        $newTable = strtolower(Str::snake($this->newName));
157
158
        $migrationName = 'rename_' . $table . '_tables';
159
160
        $migrationPath = $this->capsule['migrations_dir'];
161
162
        $fullPath = $this->laravel['migration.creator']->create($migrationName, $migrationPath);
163
164
        $stub = str_replace(
165
            [
166
                '{{table}}',
167
                '{{newTable}}',
168
                '{{singularTableName}}',
169
                '{{newSingularTableName}}',
170
                '{{tableClassName}}',
171
            ],
172
            [
173
                $table,
174
                $newTable,
175
                Str::singular($table),
176
                Str::singular($newTable),
177
                $this->currentName,
178
            ],
179
            $this->filesystem->get(__DIR__ . '/stubs/migration_rename.stub')
180
        );
181
182
        $this->filesystem->put($fullPath, $stub);
183
    }
184
185
    private function renameCapsuleDirectory()
186
    {
187
        $newCapsulePath = $this->capsule['base_path'] . '/' . $this->newName;
188
189
        $this->filesystem->move($this->capsule['root_path'], $newCapsulePath);
190
    }
191
192
    /**
193
     * Replace a given string within a given file.
194
     *
195
     * @param  array|string  $search
196
     * @param  array|string  $replace
197
     * @param  string  $path
198
     * @return void
199
     */
200
    private function replaceInFile($search, $replace, $path)
201
    {
202
        file_put_contents($path, str_replace($search, $replace, file_get_contents($path)));
203
    }
204
}
205