@@ -1954,20 +1954,24 @@ namespace Bones {
19541954 */
19551955 protected function deploy ($ argv )
19561956 {
1957- // check if there is '--wp' in the arguments array
1957+ // Check if there is '--wp' in the arguments array.
19581958 $ is_wp_org = in_array ('--wp ' , $ argv , true );
19591959
1960- // check if there is '--no-build' in the arguments array
1960+ // Check if there is '--create-zip' in the arguments array.
1961+ $ is_create_zip = in_array ('--create-zip ' , $ argv , true );
1962+
1963+ // Check if there is '--no-build' in the arguments array.
19611964 $ no_build = in_array ('--no-build ' , $ argv , true );
19621965
1963- // check if there is '--pkgm=<package-manager>' in the arguments array
1964- // and get the <package-manager> name
1966+ // Check if there is '--pkgm=<package-manager>' in the arguments array,
1967+ // and get the <package-manager> name.
19651968 $ package_name = $ this ->getOptionValue ($ argv , '--pkgm= ' );
19661969
1967- // filter the array to remove the '--wp' and '--pkgm=<package-manager>' arguments
1968- $ filtered_args = $ this ->removeValues ($ argv , ['--wp ' , '--no-build ' , '--pkgm= ' . $ package_name ]);
1970+ // Filter the array to remove the '--wp', '--create-zip', '--no-build',
1971+ // and '--pkgm=<package-manager>' arguments.
1972+ $ filtered_args = $ this ->removeValues ($ argv , ['--wp ' , '--create-zip ' , '--no-build ' , '--pkgm= ' . $ package_name ]);
19691973
1970- // get the path from the filtered arguments array
1974+ // Get the path from the filtered arguments array.
19711975 $ path = $ filtered_args [0 ] ?? '' ;
19721976 $ path = rtrim ($ path , '/ ' );
19731977
@@ -1980,6 +1984,7 @@ namespace Bones {
19801984 $ this ->info (" path \t\tThe complete path of deploy. \n" );
19811985 $ this ->line ('Options: ' );
19821986 $ this ->info (" --wp \t\t\t\tYou are going to release this plugin in the WordPress.org public repository. " );
1987+ $ this ->info (" --create-zip \t\t\tCreates an installable plugin zip file instead of deploying in a directory. " );
19831988 $ this ->info (" --pkgm=<package-manager> \tForces the deployment to use the specified package manager, Eg. npm, yarn, ... " );
19841989 $ this ->info (" --no-build \t\t\tForces the deployment to skip the build process. " );
19851990 exit (0 );
@@ -1994,7 +1999,7 @@ namespace Bones {
19941999
19952000 $ this ->do_action ('wpbones_console_deploy_start ' , $ this , $ path );
19962001
1997- // alternative method to customize the deployment
2002+ // Alternative method to customize the deployment.
19982003 if ($ this ->wpLoaded ) {
19992004 @include 'deploy.php ' ;
20002005 } else {
@@ -2038,7 +2043,14 @@ namespace Bones {
20382043 $ this ->buildAssets ($ path , $ package_name );
20392044 }
20402045
2041- // check if the destination folder exists
2046+ // When creating a zip, a temporary folder must be created with the deployed version first.
2047+ // Append "-tmp" to the path. This folder will be deleted at the end of the deployment.
2048+ if ($ is_create_zip ) {
2049+ $ originalPath = $ path ;
2050+ $ path .= '-tmp ' ;
2051+ }
2052+
2053+ // Check if the destination folder exists.
20422054 if (is_dir ($ path )) {
20432055 $ this ->startProgress ("Delete destination folder 📁 {$ path }" );
20442056 sleep (5 );
@@ -2107,10 +2119,76 @@ namespace Bones {
21072119 */
21082120 $ this ->do_action ('wpbones_console_deploy_completed ' , $ this , $ path );
21092121
2122+ // Create a zip if "--create-zip" is passed as an argument.
2123+ if ($ is_create_zip ) {
2124+ // Return an error if the zip extension is disabled.
2125+ if (!extension_loaded ('zip ' )) {
2126+ // Delete the temporary folder once the zip can't be created.
2127+ $ this ->deleteDirectory ($ path );
2128+ $ this ->error ("Can't create zip! PHP zip extension is disabled. " );
2129+ exit (1 );
2130+ }
2131+
2132+ // If the path ends with a trailing slash, remove it.
2133+ if (substr ($ originalPath , -1 ) === DIRECTORY_SEPARATOR ) {
2134+ $ originalPath = substr ($ originalPath , 0 , -1 );
2135+ }
2136+
2137+ // If the path doesn't end with .zip, add it.
2138+ if (substr ($ originalPath , -4 ) !== '.zip ' ) {
2139+ $ originalPath .= '.zip ' ;
2140+ }
2141+
2142+ // Create zip file if it doesn't exist. Needed for realpath().
2143+ fopen ($ originalPath , 'wa+ ' );
2144+
2145+ // Create the zip by iterating over the folders and files and adding them to the zip.
2146+ $ this ->startProgress ("Creating zip file 📁 {$ originalPath }" );
2147+ $ zip = new \ZipArchive ();
2148+ $ zip ->open (realpath ($ originalPath ), \ZipArchive::CREATE | \ZipArchive::OVERWRITE );
2149+ $ this ->addDirToZip ($ zip , realpath ($ path ));
2150+ $ zip ->close ();
2151+ $ this ->endProgress ();
2152+
2153+ // Delete the temporary folder after the zip is created.
2154+ $ this ->deleteDirectory ($ path );
2155+ // Update the path to the zip file for info message below.
2156+ $ path = $ originalPath ;
2157+ }
2158+
21102159 $ this ->success ("Deploy completed! " );
21112160 $ this ->info ("\n🚀 You can now deploy the plugin from the path: {$ path }\n" );
21122161 }
21132162
2163+ /**
2164+ * Recursively adds all files and directories from $folderPath to $zip with the correct relative paths.
2165+ *
2166+ * @since 1.9.4
2167+ * @param \ZipArchive $zip
2168+ * @param string $folderPath
2169+ *
2170+ * @return void
2171+ */
2172+ protected function addDirToZip ($ zip , $ folderPath ) {
2173+ $ iterator = new \RecursiveIteratorIterator (
2174+ new \RecursiveDirectoryIterator ($ folderPath , \RecursiveDirectoryIterator::SKIP_DOTS ),
2175+ \RecursiveIteratorIterator::SELF_FIRST
2176+ );
2177+
2178+ foreach ($ iterator as $ item ) {
2179+ $ realPath = $ item ->getRealPath ();
2180+ $ relativePath = substr ($ realPath , strlen ($ folderPath ) + 1 );
2181+
2182+ if ($ item ->isDir ()) {
2183+ // Create empty directory.
2184+ $ zip ->addEmptyDir ($ relativePath );
2185+ } else {
2186+ // Add file to the proper path in the zip.
2187+ $ zip ->addFile ($ realPath , $ relativePath );
2188+ }
2189+ }
2190+ }
2191+
21142192 /**
21152193 * Build assets
21162194 *
0 commit comments