1<?php 2 3namespace Illuminate\Database\Migrations; 4 5use Closure; 6use Illuminate\Support\Str; 7use InvalidArgumentException; 8use Illuminate\Filesystem\Filesystem; 9 10class MigrationCreator 11{ 12 /** 13 * The filesystem instance. 14 * 15 * @var \Illuminate\Filesystem\Filesystem 16 */ 17 protected $files; 18 19 /** 20 * The registered post create hooks. 21 * 22 * @var array 23 */ 24 protected $postCreate = []; 25 26 /** 27 * Create a new migration creator instance. 28 * 29 * @param \Illuminate\Filesystem\Filesystem $files 30 * @return void 31 */ 32 public function __construct(Filesystem $files) 33 { 34 $this->files = $files; 35 } 36 37 /** 38 * Create a new migration at the given path. 39 * 40 * @param string $name 41 * @param string $path 42 * @param string|null $table 43 * @param bool $create 44 * @return string 45 * 46 * @throws \Exception 47 */ 48 public function create($name, $path, $table = null, $create = false) 49 { 50 $this->ensureMigrationDoesntAlreadyExist($name); 51 52 // First we will get the stub file for the migration, which serves as a type 53 // of template for the migration. Once we have those we will populate the 54 // various place-holders, save the file, and run the post create event. 55 $stub = $this->getStub($table, $create); 56 57 $this->files->put( 58 $path = $this->getPath($name, $path), 59 $this->populateStub($name, $stub, $table) 60 ); 61 62 // Next, we will fire any hooks that are supposed to fire after a migration is 63 // created. Once that is done we'll be ready to return the full path to the 64 // migration file so it can be used however it's needed by the developer. 65 $this->firePostCreateHooks($table); 66 67 return $path; 68 } 69 70 /** 71 * Ensure that a migration with the given name doesn't already exist. 72 * 73 * @param string $name 74 * @return void 75 * 76 * @throws \InvalidArgumentException 77 */ 78 protected function ensureMigrationDoesntAlreadyExist($name) 79 { 80 if (class_exists($className = $this->getClassName($name))) { 81 throw new InvalidArgumentException("A {$className} class already exists."); 82 } 83 } 84 85 /** 86 * Get the migration stub file. 87 * 88 * @param string|null $table 89 * @param bool $create 90 * @return string 91 */ 92 protected function getStub($table, $create) 93 { 94 if (is_null($table)) { 95 return $this->files->get($this->stubPath().'/blank.stub'); 96 } 97 98 // We also have stubs for creating new tables and modifying existing tables 99 // to save the developer some typing when they are creating a new tables 100 // or modifying existing tables. We'll grab the appropriate stub here. 101 $stub = $create ? 'create.stub' : 'update.stub'; 102 103 return $this->files->get($this->stubPath()."/{$stub}"); 104 } 105 106 /** 107 * Populate the place-holders in the migration stub. 108 * 109 * @param string $name 110 * @param string $stub 111 * @param string|null $table 112 * @return string 113 */ 114 protected function populateStub($name, $stub, $table) 115 { 116 $stub = str_replace('DummyClass', $this->getClassName($name), $stub); 117 118 // Here we will replace the table place-holders with the table specified by 119 // the developer, which is useful for quickly creating a tables creation 120 // or update migration from the console instead of typing it manually. 121 if (! is_null($table)) { 122 $stub = str_replace('DummyTable', $table, $stub); 123 } 124 125 return $stub; 126 } 127 128 /** 129 * Get the class name of a migration name. 130 * 131 * @param string $name 132 * @return string 133 */ 134 protected function getClassName($name) 135 { 136 return Str::studly($name); 137 } 138 139 /** 140 * Get the full path to the migration. 141 * 142 * @param string $name 143 * @param string $path 144 * @return string 145 */ 146 protected function getPath($name, $path) 147 { 148 return $path.'/'.$this->getDatePrefix().'_'.$name.'.php'; 149 } 150 151 /** 152 * Fire the registered post create hooks. 153 * 154 * @param string|null $table 155 * @return void 156 */ 157 protected function firePostCreateHooks($table) 158 { 159 foreach ($this->postCreate as $callback) { 160 call_user_func($callback, $table); 161 } 162 } 163 164 /** 165 * Register a post migration create hook. 166 * 167 * @param \Closure $callback 168 * @return void 169 */ 170 public function afterCreate(Closure $callback) 171 { 172 $this->postCreate[] = $callback; 173 } 174 175 /** 176 * Get the date prefix for the migration. 177 * 178 * @return string 179 */ 180 protected function getDatePrefix() 181 { 182 return date('Y_m_d_His'); 183 } 184 185 /** 186 * Get the path to the stubs. 187 * 188 * @return string 189 */ 190 public function stubPath() 191 { 192 return __DIR__.'/stubs'; 193 } 194 195 /** 196 * Get the filesystem instance. 197 * 198 * @return \Illuminate\Filesystem\Filesystem 199 */ 200 public function getFilesystem() 201 { 202 return $this->files; 203 } 204} 205