1
+ <?php
2
+ namespace webvimark \migrate ;
3
+
4
+ use yii \console \controllers \MigrateController ;
5
+ use yii \helpers \ArrayHelper ;
6
+ use Yii ;
7
+
8
+ /**
9
+ * This class automatically scan for migrations in all available modules.
10
+ *
11
+ * ```php
12
+ * 'controllerMap' => [
13
+ * 'migrate' => [
14
+ * 'class' => 'webvimark\migrate\Controller',
15
+ * 'configs' => [
16
+ * 'config/console.php',
17
+ * 'config/web.php',
18
+ * ],
19
+ * ],
20
+ * ],
21
+ * ```
22
+ * Class Controller
23
+ * @package webvimark\migrate
24
+ */
25
+ class Controller extends MigrateController
26
+ {
27
+ /**
28
+ * Configs with modules that will be scanned. Example
29
+ *
30
+ * ```php
31
+ * 'configs' => [
32
+ * 'config/console.php',
33
+ * 'config/web.php',
34
+ * ],
35
+ * ```
36
+ *
37
+ * @var array
38
+ */
39
+ public $ configs = [];
40
+ /**
41
+ * Scan new migrations only in modules listed here
42
+ *
43
+ * @var array
44
+ */
45
+ public $ onlyModules = [];
46
+ /**
47
+ * Do not scan new migrations in modules listed here
48
+ *
49
+ * @var array
50
+ */
51
+ public $ exceptModules = [];
52
+ /**
53
+ * You can specify additional paths. Example:
54
+ *
55
+ * ```php
56
+ * 'additionalPaths' => [
57
+ * '@yii/rbac/migrations',
58
+ * 'some-path/some-dir',
59
+ * ],
60
+ * ```
61
+ *
62
+ * @var array
63
+ */
64
+ public $ additionalPaths = [];
65
+
66
+ /**
67
+ * @inheritdoc
68
+ * @since 2.0.8
69
+ */
70
+ public function optionAliases ()
71
+ {
72
+ return array_merge (parent ::optionAliases (), [
73
+ 'i ' => 'interactive ' ,
74
+ ]);
75
+ }
76
+
77
+ /**
78
+ * @inheritdoc
79
+ */
80
+ protected function getNewMigrations ()
81
+ {
82
+ $ migrations = $ this ->scanNewMigrations ($ this ->migrationPath );
83
+
84
+ foreach ($ this ->additionalPaths as $ additionalPath ) {
85
+ $ migrations = ArrayHelper::merge (
86
+ $ migrations ,
87
+ $ this ->scanNewMigrations (Yii::getAlias ($ additionalPath ))
88
+ );
89
+ }
90
+
91
+ $ mergedConfig = [];
92
+
93
+ foreach ($ this ->configs as $ configFile ) {
94
+ $ mergedConfig = ArrayHelper::merge ($ mergedConfig , require Yii::getAlias ($ configFile ));
95
+ }
96
+
97
+ if ($ mergedConfig && isset ($ mergedConfig ['modules ' ])) {
98
+
99
+ Yii::$ app ->setModules ($ mergedConfig ['modules ' ]);
100
+
101
+ foreach (Yii::$ app ->getModules () as $ moduleId => $ data ) {
102
+ if (!empty ($ this ->onlyModules ) && !in_array ($ moduleId , $ this ->exceptModules )) {
103
+ continue ;
104
+ }
105
+
106
+ if (in_array ($ moduleId , $ this ->exceptModules )) {
107
+ continue ;
108
+ }
109
+
110
+ $ migrations = ArrayHelper::merge (
111
+ $ migrations ,
112
+ $ this ->scanNewMigrations (Yii::$ app ->getModule ($ moduleId )->getBasePath () . '/migrations ' )
113
+ );
114
+ }
115
+ }
116
+ asort ($ migrations );
117
+
118
+ // Do to use array_flip to exclude possible problem with similar names that wil became array keys
119
+ foreach ($ migrations as $ path => &$ name ) {
120
+ $ name = $ path ;
121
+ }
122
+
123
+ return $ migrations ;
124
+ }
125
+
126
+ /**
127
+ * Returns the migrations that are not applied.
128
+ *
129
+ * @param string $migrationPath
130
+ *
131
+ * @return array list of new migrations
132
+ */
133
+ protected function scanNewMigrations ($ migrationPath )
134
+ {
135
+ $ applied = [];
136
+ foreach ($ this ->getMigrationHistory (null ) as $ version => $ time ) {
137
+ $ applied [$ version ] = true ;
138
+ }
139
+
140
+ $ migrations = [];
141
+ if (!is_dir ($ migrationPath )) {
142
+ return [];
143
+ }
144
+ $ handle = opendir ($ migrationPath );
145
+ while (($ file = readdir ($ handle )) !== false ) {
146
+ if ($ file === '. ' || $ file === '.. ' ) {
147
+ continue ;
148
+ }
149
+ $ path = $ migrationPath . DIRECTORY_SEPARATOR . $ file ;
150
+ if (preg_match ('/^(m(\d{6}_\d{6})_.*?)\.php$/ ' , $ file , $ matches ) && is_file ($ path )) {
151
+
152
+ if (strpos ($ path , Yii::$ app ->vendorPath ) === 0 ) {
153
+ $ path = substr_replace ($ path , '@vendor ' , 0 , strlen (Yii::$ app ->vendorPath ));
154
+
155
+ } elseif (strpos ($ path , Yii::$ app ->basePath ) === 0 ) {
156
+ $ path = substr_replace ($ path , '@app ' , 0 , strlen (Yii::$ app ->basePath ));
157
+ }
158
+
159
+ $ path = substr ($ path , 0 , -4 ); // remove ".php"
160
+
161
+ if (!isset ($ applied [$ path ])) {
162
+ $ migrations [$ path ] = $ matches [1 ];
163
+ }
164
+ }
165
+ }
166
+ closedir ($ handle );
167
+
168
+ return $ migrations ;
169
+ }
170
+
171
+ /**
172
+ * Creates a new migration instance.
173
+ * @param string $class the migration class name
174
+ * @return \yii\db\MigrationInterface the migration instance
175
+ */
176
+ protected function createMigration ($ class )
177
+ {
178
+ $ file = Yii::getAlias ($ class . '.php ' );
179
+ require_once ($ file );
180
+
181
+ $ parts = explode ('/m ' , $ class );
182
+
183
+ $ className = 'm ' . end ($ parts );
184
+
185
+ return new $ className ();
186
+ }
187
+ }
0 commit comments