@@ -29,7 +29,12 @@ class SiteDbImportCommand extends SiteBaseCommand {
2929 *
3030 * @var
3131 */
32- protected $ filename = NULL ;
32+ protected $ file = NULL ;
33+
34+ /**
35+ * The temporary path to this db.
36+ */
37+ protected $ tmpFolder = '/tmp/ ' ;
3338
3439 /**
3540 * {@inheritdoc}
@@ -90,35 +95,25 @@ protected function execute(InputInterface $input, OutputInterface $output) {
9095 parent ::execute ($ input , $ output );
9196
9297 // Check if a dump file has been specified.
93- if ($ input ->hasOption ('file ' ) &&
94- !is_null ($ input ->getOption ('file ' ))
95- ) {
96- $ this ->filename = $ input ->getOption ('file ' );
98+ if ($ input ->hasOption ('file ' ) && !is_null ($ input ->getOption ('file ' ))) {
99+ $ this ->file = $ input ->getOption ('file ' );
97100 }
101+ // Check if a dump file is set in the yaml config
98102 elseif (isset ($ this ->config ['db ' ]['dump ' ])) {
99103 // Use config from sites.yml.
100- $ this ->filename = $ this ->config ['db ' ]['dump ' ];
104+ $ this ->file = $ this ->config ['db ' ]['dump ' ];
101105 }
102106 else {
103107 throw new SiteCommandException ('Please specify a file to import the dump from ' );
104108 }
105109
106- // If the db dump is not local, download it locally.
107- if (! stream_is_local ( $ this -> filename )) {
108- $ this -> filename = $ this -> download ( $ this ->filename );
109- }
110+ // If we're installing from a dump that's not already in
111+ // our local destination, copy it to our local destination.
112+ if (! empty ( $ this ->file )) {
113+ $ this -> file = $ this -> copy ( $ this -> file );
110114
111- // Check if the file exits.
112- if (!$ this ->is_absolute_path ($ this ->filename )) {
113- $ filename = realpath (getcwd () . trim ($ this ->filename , '. ' ));
114- if (!$ this ->fileExists ($ filename )) {
115- throw new SiteCommandException (sprintf ('Dump file %s doesn \'t exist ' ,
116- $ this ->filename )
117- );
118- }
119- else {
120- $ this ->filename = $ filename ;
121- }
115+ // If the file is gzipped we need to unzip it.
116+ $ this ->file = $ this ->unzip ($ this ->file );
122117 }
123118
124119 $ this ->destination = $ this ->settingsPhpDirectory ();
@@ -154,7 +149,7 @@ protected function execute(InputInterface $input, OutputInterface $output) {
154149 }
155150
156151 // If a dump file wasn't found or not specified, do a fresh site install
157- if (!$ this ->fileExists ($ this ->filename )) {
152+ if (empty ( $ this -> file ) || !$ this ->fileExists ($ this ->file )) {
158153 //@todo Use drupal site:install instead of Drush.
159154 $ command = sprintf (
160155 'cd %s && ' .
@@ -169,62 +164,16 @@ protected function execute(InputInterface $input, OutputInterface $output) {
169164 $ this ->io ->comment ('Installing site ' );
170165 }
171166 else {
172- $ command = '' ;
173- // Check the format of the dump.
174- switch (mime_content_type ($ this ->filename )) {
175- case 'application/x-gzip ' :
176-
177- // The basename without any path.
178- $ baseNameGz = basename ($ this ->filename );
179-
180- // The basename with sql extension.
181- $ baseNameSql = str_replace ('.sql.gz ' , '.sql ' , $ baseNameGz );
182-
183- $ this ->io ->write (sprintf ('Checking if dump exists locally: ' ));
184- if ($ this ->fileExists ('/tmp/ ' . $ baseNameGz )) {
185- $ this ->io ->writeln ('Yes ' );
186- }
187- else {
188- $ this ->io ->writeln ('No ' );
189- }
190-
191- $ this ->io ->write (sprintf ('Checking if local dump is up to date: ' ));
192- if (filesize ('/tmp/ ' . $ baseNameGz ) != filesize ($ this ->filename )) {
193- $ this ->io ->writeln ('No ' );
194-
195- // Copy file to /tmp.
196- $ command .= sprintf (
197- 'cp -L %s /tmp; ' ,
198- $ this ->filename
199- );
200- }
201- else {
202- $ this ->io ->writeln ('Yes ' );
203- }
204-
205- // Unzip sql file and keep zipped in the folder.
206- $ command .= sprintf (
207- 'cd /tmp; ' .
208- 'gunzip -c %s > %s; ' ,
209- $ baseNameGz ,
210- $ baseNameSql
211- );
212-
213- // Use the file extracted on tmp folder.
214- $ this ->filename = '/tmp/ ' . $ baseNameSql ;
215- break ;
216- }
217-
218167 if (is_null ($ input ->getOption ('db-name ' ))) {
219168 $ input ->setOption ('db-name ' , $ this ->siteName );
220169 }
221- $ command . = sprintf (
170+ $ command = sprintf (
222171 'cd %s; ' .
223172 'drush sql-create %s -y; ' .
224173 'drush sql-cli < %s; ' ,
225174 $ this ->destination ,
226175 $ input ->getOption ('db-name ' ),
227- $ this ->filename
176+ $ this ->file
228177 );
229178 $ this ->io ->comment ('Importing dump ' );
230179 }
@@ -249,24 +198,42 @@ protected function execute(InputInterface $input, OutputInterface $output) {
249198 }
250199
251200 /**
252- * Downloads the dump from s3 bucket .
201+ * Downloads or copies the dump to a local destination .
253202 *
254- * @param $filename
203+ * Can be copied from a remote or local desintaiton.
255204 *
256- * @return string The absolute path for the dump.
205+ * @param $file
206+ * The file to be copied.
207+ *
208+ * @return string
209+ * The absolute path for the dump.
257210 *
258211 * @throws SiteCommandException
259212 */
260- protected function download ($ filename ) {
261- $ tmp_folder = '/tmp/ ' ;
213+ protected function copy ($ file ) {
214+ // Sanitise the input file path.
215+ $ file = $ this ->cleanFileName ($ file );
216+ $ filename = basename ($ file );
217+
218+ // Return canonicalized absolute pathname for local files.
219+ if (stream_is_local ($ file )) {
220+ $ file = realpath ($ file );
221+ }
222+
223+ // Check we're not explicitly using a file in the local destination.
224+ if (substr ($ file , 0 , strlen ($ this ->tmpFolder )) === $ this ->tmpFolder ) {
225+ return $ file ;
226+ }
262227
263- // Save the dbdump to a local destination.
264- if ('s3 ' === parse_url ($ filename , PHP_URL_SCHEME )) {
228+ // Save the db dump from S3 to the local destination.
229+ // We use S3cmd because the stream_wrapper isn't authenticated
230+ // and because it validates the checksum for us.
231+ if ('s3 ' === parse_url ($ file , PHP_URL_SCHEME )) {
265232 $ command = sprintf (
266233 'cd %s && ' .
267- 's3cmd --force get %s ' ,
268- $ tmp_folder ,
269- $ filename
234+ 's3cmd --force --check-md5 get %s ' ,
235+ $ this -> tmpFolder ,
236+ $ file
270237 );
271238
272239 $ shellProcess = $ this ->getShellProcess ();
@@ -277,26 +244,87 @@ protected function download($filename) {
277244 throw new SiteCommandException ($ shellProcess ->getOutput ());
278245 }
279246 }
247+ // For all other methods including remote and local files
248+ // we copy chunk by chunk to the local destination.
280249 else {
250+ // Check the file isn't already downloaded.
251+ $ this ->io ->write (sprintf ('Checking if db dump needs updating: ' ));
252+ if ($ this ->fileExists ($ this ->tmpFolder . $ filename ) && md5_file ($ this ->tmpFolder . $ filename ) === md5_file ($ file )) {
253+ $ this ->io ->writeln ('No ' );
254+ return $ this ->tmpFolder . $ filename ;
255+ }
256+ $ this ->io ->writeln ('Yes ' );
257+
281258 // Open a stream in read-only mode
282- if ($ stream = fopen ($ filename , 'r ' )) {
259+ if ($ stream = fopen ($ file , 'r ' )) {
283260 // Open the destination file to save the output to.
284- $ output_file = fopen ( $ tmp_folder . basename ( $ filename) , "a " );
285- if ($ output_file )
286- while (!feof ($ stream )) {
261+ $ output_file = fopen ( $ this -> tmpFolder . $ filename , "a " );
262+ if ($ output_file ) {
263+ while (!feof ($ stream )) {
287264 fwrite ($ output_file , fread ($ stream , 1024 ), 1024 );
288265 }
266+ }
289267 fclose ($ stream );
290268 if ($ output_file ) {
291269 fclose ($ output_file );
292270 }
293271 }
294272 else {
295- throw new SiteCommandException ("The DB dump could not be saved to the local destination . " );
273+ throw new SiteCommandException ("The DB dump does not exist or is not readable . " );
296274 }
297275 }
298276
299- return $ tmp_folder . basename ($ filename );
277+ // Check that the db dump has been saved.
278+ if (!$ this ->fileExists ($ this ->tmpFolder . $ filename )) {
279+ throw new SiteCommandException ("The DB dump could not be saved to the local destination. " );
280+ }
281+ $ this ->io ->success (sprintf ('The DB dump was copied to %s. ' , $ this ->tmpFolder . $ filename ));
282+
283+ return $ this ->tmpFolder . $ filename ;
284+ }
285+
286+ /**
287+ * @param $file
288+ * The zipped file to be extracted.
289+ *
290+ * @return string
291+ * The unzipped file.
292+ *
293+ * @throws SiteCommandException
294+ */
295+ public function unzip ($ file ) {
296+ // The basename without any path.
297+ $ baseNameGz = basename ($ file );
298+ // The basename with sql extension.
299+ $ baseNameSql = rtrim ($ baseNameGz , '.gz ' );
300+
301+ // Unzip sql file and keep zipped in the folder.
302+ if (mime_content_type ($ this ->file ) === 'application/x-gzip ' ) {
303+ $ command = sprintf (
304+ 'cd %s; ' .
305+ 'gunzip -c %s > %s; ' ,
306+ $ this ->tmpFolder ,
307+ $ baseNameGz ,
308+ $ baseNameSql
309+ );
310+ }
311+ // Return the file without modification.
312+ else {
313+ return $ file ;
314+ }
315+
316+ // Run unzip command.
317+ $ shellProcess = $ this ->getShellProcess ();
318+ if ($ shellProcess ->exec ($ command , TRUE )) {
319+ $ this ->io ->writeln ($ shellProcess ->getOutput ());
320+ $ this ->io ->success (sprintf ("The DB dump was unzipped to %s " , $ this ->tmpFolder . $ baseNameSql ));
321+ }
322+ else {
323+ throw new SiteCommandException ($ shellProcess ->getOutput ());
324+ }
325+
326+ // Use the file extracted on tmp folder.
327+ return $ this ->tmpFolder . $ baseNameSql ;
300328 }
301329
302330}
0 commit comments