Zip下载ZIP更改Wordpress主题的文件夹名称

时间:2013-11-19 20:19:17

标签: php wordpress github zip

我一直试图解决这个问题,但似乎无法找到任何东西。

当您从github“下载ZIP”时,它不会为您提供您希望的“ theme_name.zip ”,而是“ theme_name-master.zip < / strong>“,当普通用户安装此文件时,混乱的文件夹名称会抛弃子主题。

如何解决这个问题,以便zip下载不会改变任何内容?

2 个答案:

答案 0 :(得分:1)

为简单起见,您可以在某处下载脚本,下载脚本,重命名不带-master的文件夹,然后重新压缩项目,然后将其发送给用户下载。

类似于(需要PHP5&gt; = 5.2.0,cURLZipArchive,safe_mode&amp; open_basedir off ):

Fork it from GitHub ;p

<?php
//Example Usage
new GitDL('https://github.com/lcherone/GitDL');

/**
 * GitHub Project/Repository Downloader proxy.
 * This class will handle downloading, removing master folder prefix, 
 * repacking and proxying back the project as a download.
 * 
 * @author Lawrence Cherone
 * @version 0.2
 */
class GitDL{
    // project files working directory - automatically created
    const PWD = "./project_files/";

    /**
     * Class construct.
     *
     * @param string $url
     */
    function __construct($url=null){
        // check construct argument
        if(!$url) die('Class Error: Missing construct argument: $url');

        // fix trailing slash if any
        $url = rtrim($url, '/');

        // assign class properties
        $this->project     = basename($url);
        $this->project_url = $url.'/archive/master.zip';
        $this->tmp_file    = md5($url).'.zip';

        // make project working folder
        if(!file_exists(self::PWD)){
            mkdir(self::PWD.md5($url), 0775, true);
        }

        // get project zip from GitHub
        try{
            $this->get_project();
        }catch(Exception $e){
            die($e->getMessage());
        }

        // extract project zip from git
        $this->extract(self::PWD.$this->tmp_file, self::PWD.md5($url));

        // remove the master part, by renaming
        rename(self::PWD.md5($url).'/'.$this->project.'-master', self::PWD.md5($url).'/'.$this->project);

        // rezip project files
        $this->zipcreate(self::PWD.md5($url), self::PWD.'new_'.$this->tmp_file);

        // send zip to user
        header('Content-Description: File Transfer');
        header('Content-Type: application/zip');
        header('Content-Disposition: attachment; filename="'.$this->project.'.zip"');
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
        header('Content-Length: '.sprintf("%u", filesize(self::PWD.'new_'.$this->tmp_file)));
        readfile(self::PWD.'new_'.$this->tmp_file);

        // cleanup
        $this->destroy_dir(self::PWD.md5($url));
        unlink(self::PWD.$this->tmp_file);
        unlink(self::PWD.'new_'.$this->tmp_file);
    }

    /**
     * cURL GitHub project downloader. 
     * No support for open base dir/safe mode as there is a GitHub redirect to there CDN
     * a HEAD pre-check is done to check project exists,
     * project zip is written directly to the file.
     */
    function get_project(){
        // check curl installed
        if(!function_exists('curl_init')){
            throw new Exception('cURL Error: You must have cURL installed to use this class.');
        }
        // check for unsupported settings
        if (ini_get('open_basedir') != '' || ini_get('safe_mode') == 'On'){
            throw new Exception('cURL Error: safe_mode or an open_basedir is enabled, class not supported.');
        }

        // HEAD request - To verify the project exists
        $ch = curl_init();
        curl_setopt_array($ch, array(
            CURLOPT_URL => $this->project_url,
            CURLOPT_TIMEOUT => 5,
            CURLOPT_CONNECTTIMEOUT => 5,
            CURLOPT_FAILONERROR => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_BINARYTRANSFER => true,
            CURLOPT_HEADER => false,
            CURLOPT_NOBODY => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_SSL_VERIFYPEER => false,
        ));

        // lets grab it
        if(curl_exec($ch) !== false){
            $fp = fopen(self::PWD.$this->tmp_file, 'a+b');
            if(flock($fp, LOCK_EX | LOCK_NB)){
                // empty possible contents
                ftruncate($fp, 0);
                rewind($fp);

                // HTTP GET request - write directly to the file
                $ch = curl_init();
                curl_setopt_array($ch, array(
                    CURLOPT_URL => $this->project_url,
                    CURLOPT_TIMEOUT => 5,
                    CURLOPT_CONNECTTIMEOUT => 5,
                    CURLOPT_FAILONERROR => true,
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_BINARYTRANSFER => true,
                    CURLOPT_HEADER => false,
                    CURLOPT_FILE => $fp,
                    CURLOPT_FOLLOWLOCATION => true,
                    CURLOPT_SSL_VERIFYHOST => false,
                    CURLOPT_SSL_VERIFYPEER => false,
                ));

                // transfer failed
                if(curl_exec($ch) === false){
                    ftruncate($fp, 0);
                    throw new Exception('cURL Error: transfer failed.');
                }
                fflush($fp);
                flock($fp, LOCK_UN);
                curl_close($ch);
            }
            fclose($fp);
        }else{
            curl_close($ch);
            throw new Exception('Error: '.htmlentities($this->project).' project not found on GitHub');
        }
    }

    /**
     * Create zip from extracted/fixed project.
     *
     * @uses ZipArchive
     * @uses RecursiveIteratorIterator
     * @param string $source
     * @param string $destination
     * @return bool
     */
    function zipcreate($source, $destination) {
        if (!extension_loaded('zip') || !file_exists($source)) {
            return false;
        }
        $zip = new ZipArchive();
        if (!$zip->open($destination, ZIPARCHIVE::CREATE)) {
            return false;
        }
        $source = str_replace('\\', '/', realpath($source));
        if (is_dir($source) === true) {
            $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
            foreach ($files as $file) {
                $file = str_replace('\\', '/', realpath($file));
                if (is_dir($file) === true) {
                    $zip->addEmptyDir(str_replace($source.'/', '', $file.'/'));
                } else if (is_file($file) === true) {
                    $zip->addFromString(str_replace($source.'/', '', $file), file_get_contents($file));
                }
            }
        }
        return $zip->close();
    }

    /**
     * Extract Zip file
     *
     * @uses ZipArchive
     * @param string $source
     * @param string $destination
     * @return bool
     */
    function extract($source, $destination){
        $zip = new ZipArchive;
        if($zip->open($source) === TRUE) {
            $zip->extractTo($destination);
            $zip->close();
            return true;
        } else {
            return false;
        }
    }

    /**
     * Recursive directory remover/deleter
     *
     * @uses RecursiveIteratorIterator
     * @param string $dir
     * @return bool
     */
    function destroy_dir($dir) {
        foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST) as $path) {
            $path->isFile() ? unlink($path->getPathname()) : rmdir($path->getPathname());
        }
        return rmdir($dir);
    }

}
?>

答案 1 :(得分:0)

这有点问题,我认为没有真正的解决方案,只有解决方法。我遇到了与插件相同的问题并且只有部分解决方案:它仅适用于插件/主题更新,而不适用于安装。

从未尝试过,但也许可以在插件(register_activation_hook)或主题(after_switch_theme)激活时执行文件夹重命名。

我检查了核心,过滤器upgrader_source_selection适用于主题和插件。 repo slug位于GitHub的URL中:http://github.com/user/repo-name

public static $repo_slug = 'repo-name';

add_filter( 'upgrader_source_selection', array( $this, 'rename_github_zip' ), 1, 3 );

/**
 * Removes the prefix "-master" when updating from GitHub zip files
 * 
 * See: https://github.com/YahnisElsts/plugin-update-checker/issues/1
 * 
 * @param string $source
 * @param string $remote_source
 * @param object $thiz
 * @return string
 */
public function rename_github_zip( $source, $remote_source, $thiz )
{
    if(  strpos( $source, self::$repo_slug ) === false )
        return $source;

    $path_parts = pathinfo($source);
    $newsource = trailingslashit($path_parts['dirname']). trailingslashit( self::$repo_slug );
    rename($source, $newsource);
    return $newsource;
}