Skip to content

Instantly share code, notes, and snippets.

@akosma
Created October 9, 2013 18:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akosma/6906241 to your computer and use it in GitHub Desktop.
Save akosma/6906241 to your computer and use it in GitHub Desktop.
This script generates a ZIP file with the contents of the current folder, without including files ending in *.zip, .DS_Store or this script itself. To actually request the file, call it using the "?download" key after the script name. This will generate and download the file immediately. It can also generate its own HTML5 manifest, so that the j…
<?php
/*
* Author: Adrian Kosmaczewski.
* License: BSD.
*
* This script generates a ZIP file with the contents of the current folder,
* without including files ending in *.zip, .DS_Store or this script itself.
*
* To actually request the file, call it using the "?download" key after the
* script name. This will generate and download the file immediately.
*
* It can also generate its own HTML5 manifest, so that the jQuery Mobile
* files are only downloaded once.
*/
// Global constants.
define("AKO_DOWNLOAD_PARAM", "download");
define("AKO_MANIFEST_PARAM", "manifest");
define("AKO_FILENAME_PREFIX", "mobile-web-");
define("AKO_JQUERY_MOBILE_CSS", "http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css");
define("AKO_JQUERY_JS", "http://code.jquery.com/jquery-1.9.1.min.js");
define("AKO_JQUERY_MOBILE_JS", "http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js");
/*
* Returns the name of the current script.
* Basename trick taken from
* http://stackoverflow.com/questions/4221333/get-the-current-script-file-name
*/
function get_current_script() {
$this_script = './' . basename(__FILE__);
return $this_script;
}
/*
* Creates a compressed zip file and returns true if it was created, or false
* otherwise.
* Adapted from
* http://davidwalsh.name/create-zip-php
*/
function create_zip($files = array(), $destination = '', $overwrite = false) {
if(file_exists($destination) && !$overwrite) {
return false;
}
$valid_files = array();
if(is_array($files)) {
foreach($files as $file) {
if(file_exists($file)) {
$valid_files[] = $file;
}
}
}
if(count($valid_files)) {
$zip = new ZipArchive();
if($zip->open($destination, $overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
return false;
}
foreach($valid_files as $file) {
$zip->addFile($file, $file);
}
$zip->close();
return file_exists($destination);
}
else {
return false;
}
}
/*
* States whether the haystack string starts with the needle string.
* Adapted from
* http://stackoverflow.com/questions/834303/php-startswith-and-endswith-functions
*/
function starts_with($haystack, $needle) {
return $needle === "" || strpos($haystack, $needle) === 0;
}
/*
* States whether the haystack string ends with the needle string.
* Adapted from
* http://stackoverflow.com/questions/834303/php-startswith-and-endswith-functions
*/
function ends_with($haystack, $needle) {
return $needle === "" || substr($haystack, -strlen($needle)) === $needle;
}
/*
* Returns an array of files including their relative paths.
* It does not include files with the ".zip" extension
* neither pathnames starting with an underscore.
* Adapted from
* http://php.net/manual/en/function.scandir.php
*/
function find_all_files($dir) {
$root = scandir($dir);
foreach($root as $value) {
if($value === '.' || $value === '..' || starts_with($value, "_")) {
continue;
}
// Adapted from
// http://stackoverflow.com/questions/10368217/php-get-file-extension
$ext = pathinfo($value, PATHINFO_EXTENSION);
if ($ext === 'zip') {
continue;
}
if(is_file("$dir/$value")) {
$result[] = "$dir/$value";
continue;
}
foreach(find_all_files("$dir/$value") as $value) {
$result[] = $value;
}
}
return $result;
}
/*
* Removes all files including the ".zip" extension in the folder specified as
* parameter. Adapted from
* http://stackoverflow.com/questions/10149101/php-delete-a-file-with-any-extension
*/
function remove_old_zip_files($dir) {
$file_pattern = "$dir/*.zip";
array_map("unlink", glob($file_pattern));
}
/*
* Generates a file name that contains the current date.
* Adapted from
* http://stackoverflow.com/questions/12298048/generate-filename-with-creation-date
*/
function generate_filename() {
$filename = AKO_FILENAME_PREFIX . date('Ymd-His') . ".zip";
return $filename;
}
/*
* Generate the zip file and return the file name.
*/
function generate_zip() {
$file = generate_filename();
$dir = '.';
remove_old_zip_files($dir);
$files = find_all_files($dir);
// Filter non-desired files in the final zip
$ds_store = './.DS_Store';
$this_script = get_current_script();
$exclude = array($this_script, $ds_store);
$files_to_zip = array_diff($files, $exclude);
$result = create_zip($files_to_zip, $file);
return $file;
}
/*
* Stream the file to the client and stop the execution of the rest of the
* script. Adapted from
* http://php.net/manual/en/function.readfile.php
*/
function download($file) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $file);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
/*
* Returns the HTML5 cache manifest of this application and stops the execution
* of the rest of the script.
*/
function get_manifest() {
header("Content-Type: text/cache-manifest");
echo("CACHE MANIFEST\n");
echo("# version 3\n");
echo("\n");
echo("CACHE:\n");
echo(AKO_JQUERY_MOBILE_CSS . "\n");
echo(AKO_JQUERY_JS . "\n");
echo(AKO_JQUERY_MOBILE_JS . "\n");
exit;
}
if (isset($_GET[AKO_DOWNLOAD_PARAM])) {
$file = generate_zip();
download($file);
}
if (isset($_GET[AKO_MANIFEST_PARAM])) {
get_manifest();
}
?>
<!DOCTYPE html>
<html lang="en" manifest="<?php echo(get_current_script() . '?' . AKO_MANIFEST_PARAM) ?>">
<head>
<meta charset="utf-8">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<title>Mobile Web Training</title>
<link href="<?php echo(AKO_JQUERY_MOBILE_CSS) ?>" rel="stylesheet" />
<script src="<?php echo(AKO_JQUERY_JS) ?>"></script>
<script src="<?php echo(AKO_JQUERY_MOBILE_JS) ?>"></script>
</head>
<body>
<div data-role="page">
<div data-role="header">
<h1>Mobile Web Training</h1>
</div>
<div data-role="content">
<p>Download the current state of the project here:</p>
<p><a data-role="button" data-ajax="false" href="<?php
echo(get_current_script() . '?' . AKO_DOWNLOAD_PARAM) ?>">Download zip file</a></p>
</div>
<div data-role="footer" data-position="fixed">
<p align="center">© Adrian Kosmaczewski - All Rights Reserved</p>
</div>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment