Last active
February 16, 2021 17:10
-
-
Save brichards/5020710 to your computer and use it in GitHub Desktop.
StartBox GitHub Download Generator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Plugin Name: StartBox GitHub .zip Generator | |
* Description: Generates a .zip download for StartBox from GitHub Master. | |
* | |
* @props Konstantin Kovshenin (@kovshenin) for sharing his work used on underscores.me (http://code.svn.wordpress.org/underscoresme/plugins/underscoresme-generator/underscoresme-generator.php) | |
*/ | |
class SB_Download_Generator { | |
/** | |
* Setup all our variables and hooks | |
*/ | |
function __construct() { | |
// Setup our variables | |
$this->github_repo = 'https://api.github.com/repos/WebDevStudios/StartBox'; // The repo we're harvesting | |
$this->last_commit_date = ( $stored = get_option( 'github_last_commit_date' ) ) ? $stored : date( 'c', strtotime('-1 year') ); // Falls back to 1yr ago | |
$this->pagename = 'download'; // The page slug we're hijacking | |
$this->filename = 'startbox.zip'; // Our desired filename | |
$this->tmp_dir = ABSPATH . 'tmp/'; // The temp directory where we'll store everything | |
$this->tmp_file = $this->tmp_dir . 'sb.zip'; // The temp zip we'll create when downloading from github | |
$this->download_file = $this->tmp_dir . $this->filename; // The download file we'll serve to everyone | |
$this->excluded_files = array( '.git', '.svn', '.DS_Store', '.gitignore', '.', '..' ); // Optional files to exclude in the served zip | |
$this->excluded_dirs = array( '.git', '.svn', '.', '..' ); // Optional directories to exclude in the served zip | |
// All the black magic is happening here | |
add_action( 'parse_request', array( $this, 'init' ) ); | |
} | |
/** | |
* Listens for a download request and fires things up | |
*/ | |
function init( &$wp ) { | |
// Listen for someone trying to access our target pagename | |
if ( $this->pagename == $wp->query_vars['pagename'] ) { | |
// If github has a newer commit, or we don't have a download file prepped, let's make a new zip | |
if ( $this->is_github_newer() || ! file_exists( $this->download_file ) ) { | |
$this->remote_get(); | |
$this->make_archive(); | |
} | |
$this->serve_download(); | |
} | |
} | |
/** | |
* Check if github has a more recent commit | |
* | |
* @return boolean True if github's commit is newer, false if current | |
*/ | |
function is_github_newer() { | |
// Grab the newest commit date | |
$remote_request = wp_remote_get( $this->github_repo . '/commits?sha=master&since=' . $this->last_commit_date ); | |
$request_body = json_decode($remote_request['body'], true ); | |
$current_commit = ( is_array( $request_body ) && !empty( $request_body ) ) ? $request_body[0]['commit']['author']['date'] : $this->last_commit_date; | |
// If current commit is newer, update option and return true | |
if ( strtotime( $current_commit ) > strtotime( $this->last_commit_date ) ) { | |
update_option( 'github_last_commit_date', $current_commit ); | |
return true; | |
} | |
// Otherwise, we're current | |
return false; | |
} | |
/** | |
* Grabs our zipball from github and unpacks it locally | |
*/ | |
function remote_get() { | |
// Fetch our file from github and save it locallaly | |
$remote_file = wp_remote_get( $this->github_repo . '/zipball' ); | |
$fp = fopen( $this->tmp_file, 'w' ); | |
fwrite( $fp, $remote_file['body'] ); | |
fclose( $fp ); | |
// Fire up ZipArchive | |
$zip = new ZipArchive; | |
$res = $zip->open( $this->tmp_file, ZipArchive::CREATE && ZipArchive::OVERWRITE ); | |
// Unzip the contents and write them to an array | |
$zip->extractTo( $this->tmp_dir . 'startbox/' ); | |
$extracted_contents = scandir( $this->tmp_dir . 'startbox/', 1 ); | |
$this->extracted_dir = trailingslashit( $this->tmp_dir . 'startbox/' . $extracted_contents[0] ); | |
// Close and delete our zip | |
$zip->close(); | |
unlink( $this->tmp_file ); | |
} | |
/** | |
* Creates a fresh archive from the unpacked files | |
*/ | |
function make_archive() { | |
// Fire up ZipArchive | |
$zip = new ZipArchive; | |
$res = $zip->open( $this->download_file, ZipArchive::CREATE && ZipArchive::OVERWRITE ); | |
// Loop through our extracted contents and add anything we havent excluded | |
$iterator = new RecursiveDirectoryIterator( $this->extracted_dir ); | |
foreach ( new RecursiveIteratorIterator( $iterator ) as $filename ) { | |
if ( in_array( basename( $filename ), $this->excluded_files ) ) | |
continue; | |
foreach ( $this->excluded_dirs as $directory ) | |
if ( strstr( $filename, "/{$directory}/" ) ) | |
continue 2; // continue the parent foreach loop | |
$local_filename = str_replace( trailingslashit( $this->extracted_dir ), '', $filename ); | |
$contents = file_get_contents( $filename ); | |
$zip->addFromString( $local_filename, $contents ); | |
} | |
// Close our zip | |
$zip->close(); | |
// Delete our temporory dir | |
// $this->remove_dir( $this->extracted_dir ); | |
} | |
/** | |
* Serves up a download for our zip | |
*/ | |
function serve_download() { | |
header( 'Content-type: application/zip' ); | |
header( sprintf( 'Content-Disposition: attachment; filename="%s"', $this->filename ) ); | |
readfile( $this->download_file ); | |
die(); | |
} | |
/** | |
* Recursively loops through a directory and deletes it plus all contents. | |
* | |
* @param string $dir The directory to delete | |
*/ | |
function remove_dir( $dir ) { | |
if ( is_dir($dir) ) { | |
$objects = scandir( $dir ); | |
foreach ( $objects as $object ) { | |
if ( '.' != $object && '..' != $object ) { | |
if ( 'dir' == filetype( $dir . '/' . $object ) ) | |
$this->remove_dir( $dir . '/' . $object ); | |
else | |
unlink( $dir . '/' . $object ); | |
} | |
} | |
reset( $objects ); | |
rmdir( $dir ); | |
} | |
} | |
} | |
new SB_Download_Generator; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment