22
33use Azi \Generators \Theme ;
44use GuzzleHttp \Client ;
5+ use GuzzleHttp \Exception \BadResponseException ;
56use RecursiveDirectoryIterator ;
67use RecursiveIteratorIterator ;
78use RuntimeException ;
89use Symfony \Component \Console \Command \Command ;
10+ use Symfony \Component \Console \Helper \ProgressBar ;
911use Symfony \Component \Console \Input \InputArgument ;
1012use Symfony \Component \Console \Input \InputInterface ;
1113use Symfony \Component \Console \Input \InputOption ;
@@ -41,7 +43,7 @@ class NewCommand extends Command
4143 *
4244 * @param null $name
4345 */
44- public function __construct ( $ name = null )
46+ public function __construct ($ name = null )
4547 {
4648 $ this ->cacheDirectory = $ this ->getCacheDirectory ();
4749 $ this ->createCacheDirectory ();
@@ -60,7 +62,7 @@ public function getApp()
6062 * @param mixed $app
6163 * @return NewCommand
6264 */
63- public function setApp ( $ app )
65+ public function setApp ($ app )
6466 {
6567 $ this ->app = $ app ;
6668 return $ this ;
@@ -78,7 +80,7 @@ public function getVersion()
7880 * @param mixed $version
7981 * @return NewCommand
8082 */
81- public function setVersion ( $ version )
83+ public function setVersion ($ version )
8284 {
8385 $ this ->version = $ version ;
8486
@@ -94,35 +96,33 @@ protected function configure()
9496 ->setName ('new ' )
9597 ->setDescription ('Create a new WordPress application with Timber. ' )
9698 ->addArgument ('name ' , InputArgument::OPTIONAL , 'Your applications \'s name ' )
97- ->addArgument ('version ' , InputArgument::OPTIONAL , 'The version of wordpress to download ' );
99+ ->addArgument ('version ' , InputArgument::OPTIONAL , 'The version of WordPress to download ' );
98100 }
99101
100102 /**
101103 * @param InputInterface $input
102104 * @param OutputInterface $output
103105 * @return int|null|void
104106 */
105- public function execute ( InputInterface $ input , OutputInterface $ output )
107+ public function execute (InputInterface $ input , OutputInterface $ output )
106108 {
107109 if (!class_exists ('ZipArchive ' )) {
108110 throw new RuntimeException ('The Zip PHP extension is not installed. Please install it and try again. ' );
109111 }
110112
111113 $ this ->verifyApplicationDoesNotExists (
112- $ directory = ( $ input ->getArgument ('name ' ) ) ? getcwd () . '/ ' . $ input ->getArgument ('name ' ) : getcwd ()
114+ $ directory = ($ input ->getArgument ('name ' )) ? getcwd () . '/ ' . $ input ->getArgument ('name ' ) : getcwd ()
113115 );
114-
115116 $ this ->setApp ($ input ->getArgument ('name ' ))->setVersion ($ input ->getArgument ('version ' ));
116117
117118 $ this ->createApplicationDirectory ();
118119
119- $ output ->writeln ('<info>Downloading wordpress..</info> this might take a while ' );
120- $ zipFile = $ this ->download ();
120+ $ zipFile = $ this ->download ($ output );
121121
122- $ output ->writeln ('<info>Extracting package</info> ' );
122+ $ output ->writeln ( '<info>Extracting package</info> ' );
123123 $ this ->extract ($ zipFile );
124124
125- $ output ->writeln ('<info>Generating wordpress theme & installing timber</info> ' );
125+ $ output ->writeln ('<info>Generating WordPress theme & installing timber</info> ' );
126126 (new Theme ($ this ->getApp (), $ input , $ output ))->generate ();
127127
128128 $ output ->writeln ('<comment>All done! Build something amazing.</comment> ' );
@@ -131,52 +131,87 @@ public function execute( InputInterface $input, OutputInterface $output )
131131 /**
132132 * Download WordPress Zip package
133133 *
134+ * @param OutputInterface $output
134135 * @return string
135136 */
136- public function download ()
137+ public function download ($ output )
137138 {
138139 $ zipFilePath = $ this ->getZipFilePath ();
139140
140141 if (file_exists ($ zipFilePath )) {
142+ $ this ->verifyZipIntegrity ();
141143 return $ zipFilePath ;
142144 }
143145
144- $ file = (new Client (['verify ' => false ]))->get ($ this ->getUrl ());
145- file_put_contents ($ zipFilePath , $ file ->getBody ());
146+ $ file = (new Client ([
147+ 'verify ' => false ,
148+ ]));
149+
150+ $ zipFileResource = fopen ($ zipFilePath , 'w ' );
151+ $ downloadProgress = new ProgressBar ($ output );
152+ $ downloadProgress ->setFormatDefinition ('custom ' , '<info>Downloading WordPress: %downloaded%%</info> ' );
153+ $ downloadProgress ->setFormat ('custom ' );
154+ $ downloadProgress ->start ();
155+ $ file ->request ('GET ' , $ this ->getUrl (), [
156+ 'sink ' => $ zipFileResource ,
157+ 'progress ' => function (
158+ $ downloadTotal ,
159+ $ downloadedBytes ,
160+ $ uploadTotal ,
161+ $ uploadedBytes
162+ ) use ($ downloadProgress ) {
163+ $ progressValue = 0 ;
164+ if ($ downloadedBytes > 0 ) {
165+ $ progressValue = ($ downloadedBytes / $ downloadTotal ) * 100 ;
166+ }
167+ $ downloadProgress ->advance ();
168+ $ downloadProgress ->setMessage (round ($ progressValue , 2 ), 'downloaded ' );
169+ },
170+ ]);
171+ $ output ->writeln ("" );
146172 return $ zipFilePath ;
147173 }
148174
149175 /**
150176 * Get WordPress ZIP file URL
151177 *
152- * @return string
178+ * @param null $checksum
179+ * @return mixed null|md5|sha1
153180 */
154- protected function getUrl ()
181+ protected function getUrl ($ checksum = null )
155182 {
183+ $ url = $ this ->baseUrl . '/latest.zip ' ;
156184 if ($ version = $ this ->getVersion ()) {
157- return $ this ->baseUrl . '/wordpress- ' . $ version . '.zip ' ;
185+ $ url = $ this ->baseUrl . '/wordpress- ' . $ version . '.zip ' ;
158186 }
159187
160- return $ this ->baseUrl . '/latest.zip ' ;
188+ if ($ checksum ) {
189+ $ url .= ". $ checksum " ;
190+ }
191+ return $ url ;
161192 }
162193
163194 /**
164195 * @param $directory
196+ * @return bool
165197 */
166- protected function verifyApplicationDoesNotExists ( $ directory )
198+ protected function verifyApplicationDoesNotExists ($ directory )
167199 {
168- if (( is_dir ($ directory ) || is_file ($ directory ) ) && $ directory != getcwd ()) {
200+ $ isEmpty = (count (glob ("$ directory/* " )) === 0 ) ? true : false ;
201+
202+ if ((is_dir ($ directory ) || is_file ($ directory )) && $ directory != getcwd () && !$ isEmpty ) {
169203 throw new RuntimeException ('Application already exists! ' );
170204 }
205+ return true ;
171206 }
172207
173208 /**
174209 * @return string
175210 */
176211 protected function getCacheDirectory ()
177212 {
178- return isset ( $ _SERVER [ 'HOME ' ] ) ?
179- $ _SERVER [ 'HOME ' ] . DIRECTORY_SEPARATOR . '.timber_installer ' . DIRECTORY_SEPARATOR :
213+ return isset ($ _SERVER ['HOME ' ] ) ?
214+ $ _SERVER ['HOME ' ] . DIRECTORY_SEPARATOR . '.timber_installer ' . DIRECTORY_SEPARATOR :
180215 getcwd ();
181216 }
182217
@@ -207,10 +242,10 @@ private function createCacheDirectory()
207242 /**
208243 * @param $file
209244 */
210- public function extract ( $ file )
245+ public function extract ($ file )
211246 {
212247 $ projectPath = getcwd () . '/ ' . $ this ->getApp ();
213- $ zip = new \ZipArchive ();
248+ $ zip = new \ZipArchive ();
214249 $ zip ->open ($ file );
215250 $ zip ->extractTo ($ projectPath );
216251
@@ -225,7 +260,7 @@ public function extract( $file )
225260 * @return bool
226261 * @link http://stackoverflow.com/a/1653776/2641971
227262 */
228- public function delete ( $ directory )
263+ public function delete ($ directory )
229264 {
230265 if (!file_exists ($ directory )) {
231266 return true ;
@@ -256,7 +291,7 @@ public function delete( $directory )
256291 * @param $destination
257292 * @link http://stackoverflow.com/a/27290570/2641971
258293 */
259- public function move ( $ source , $ destination )
294+ public function move ($ source , $ destination )
260295 {
261296 $ this ->fileSystem = new Filesystem ();
262297
@@ -265,7 +300,7 @@ public function move( $source, $destination )
265300 }
266301
267302 $ directoryIterator = new \RecursiveDirectoryIterator ($ source , \RecursiveDirectoryIterator::SKIP_DOTS );
268- $ iterator = new \RecursiveIteratorIterator ($ directoryIterator , \RecursiveIteratorIterator::SELF_FIRST );
303+ $ iterator = new \RecursiveIteratorIterator ($ directoryIterator , \RecursiveIteratorIterator::SELF_FIRST );
269304 foreach ($ iterator as $ item ) {
270305
271306 if ($ item ->isDir ()) {
@@ -282,6 +317,25 @@ public function move( $source, $destination )
282317 */
283318 protected function createApplicationDirectory ()
284319 {
285- mkdir (getcwd () . '/ ' . $ this ->getApp ());
320+ $ directory = getcwd () . '/ ' . $ this ->getApp ();
321+ if (is_dir ($ directory ) && !file_exists ($ directory )) {
322+ mkdir ($ directory );
323+ }
324+ }
325+
326+ /**
327+ * @param string $algorithm md5|sha1
328+ * @throws \Exception
329+ */
330+ protected function verifyZipIntegrity ($ algorithm = 'md5 ' )
331+ {
332+ $ request = new Client ();
333+ $ response = $ request ->get ($ this ->getUrl ($ algorithm ));
334+ $ remoteChecksum = $ response ->getBody ();
335+ $ localChecksum = md5_file ($ this ->getZipFilePath ());
336+ if ($ algorithm == 'md5 ' && ($ remoteChecksum != $ localChecksum )) {
337+ unlink ($ this ->getZipFilePath ());
338+ throw new \Exception ("Cannot verify integrity of {$ this ->getZipFilePath ()}. \n We have deleted the file. \n Please try again. " );
339+ }
286340 }
287341}
0 commit comments