Viewing File: /usr/local/cpanel/3rdparty/wpinstaller/src/WpInstaller/FileManager.php

<?php
namespace WpInstaller;

class FileManager {
    private $created_files = [];
    private $created_folders = [];

    public function copy_file($source, $dest, $overwrite = false) {
        if (file_exists($dest) && !$overwrite) {
            throw new \Exception("Failed to copy to: $dest. File exists.");
        }
        else {
            if (copy($source, $dest) !== true) {
                throw new \Exception("Failed to copy file to: $dest");
            }
            $this->created_files[$dest] = md5_file($dest);
        }
    }

    public function copy_dir($source, $dest, $overwrite = false) {
        // If the dest folder doesn't exist, create it.
        $this->mkdir($dest);

        $cur_dir = opendir($source);

        if ($cur_dir === false) {
            throw new \Exception("Failed to read from: $source");
        }

        while (($entry = readdir($cur_dir)) !== false) {
            if ($entry != '.' && $entry != '..') {
                $s_path = "$source/$entry";
                $d_path = "$dest/$entry";

                if (is_dir($s_path)) {
                    $this->copy_dir($s_path, $d_path, $overwrite);
                }
                else {
                    $this->copy_file($s_path, $d_path, $overwrite);
                }
            }
        }

        closedir($cur_dir);
    }

    public function mkdir($directory) {
        if (!file_exists($directory) || !is_dir($directory)) {
            if (mkdir($directory, 0755, true) !== true) {
                throw new \Exception("Failed to create directory: $directory");
            }

            array_push($this->created_folders, $directory);
        }
    }

    /* transform_file(string $file, callable $trans_func)

        // Example: replace all instances of 'hello' with 'hi' in a file
        $func = function ( $line ) { return str_replace( 'hello', 'hi', $line); }
        transform_file('foo.txt', $func);

        Note: Since copy_file() is used to overwrite the input file with the new file contents, a
              call to rollback() will delete files modified by transform_file
    */
    public function transform_file(string $file, callable $trans_func) {
        // Open input file for reading
        $input_handle = fopen($file, 'r');

        if (!$input_handle) {
            throw new \Exception("Could not open file: $file");
        }

        if( !flock($input_handle, LOCK_EX) ) {
            throw new \Exception("Could not get lock on: $file for transform");
        }
        else {
            // Write transformations out to a temp file
            $output_handle = tmpfile();

            while ( ($line = fgets($input_handle)) !== false ) {
                if (fwrite($output_handle, $trans_func( $line )) === false) {
                    throw new \Exception("Failed to write to $file");
                }
            }

            // Fail if we got 'false' from fgets() before reaching the end of the file
            if (!feof($input_handle)) {
                fclose($input_handle);
                fclose($output_handle);
                throw new \Exception("Error reading while transforming: $file");
            }

            if (!fflush($output_handle)) {
                throw new \Exception("Failed to finish writing to $file");
            }
            fclose($input_handle);

            // Replace the input file with the output file
            $out_path = stream_get_meta_data($output_handle)['uri'];
            $this->copy_file($out_path, $file, true);

            fclose($output_handle);
        }
    }

    public function rollback() {
        $this->undo_created_files();
        $this->undo_created_folders();
    }

    private function undo_created_files() {
        foreach ($this->created_files as $file => $hash) {
            if (md5_file($file) == $hash) {
                unlink($file);
            }
        }
    }

    private function undo_created_folders() {
        $created_folders = array_reverse($this->created_folders);

        foreach ($created_folders as $folder) {
            $is_empty = !(new \FilesystemIterator($folder))->valid();
            if ($is_empty) {
                rmdir($folder);
            }
        }
    }
}

?>
Back to Directory File Manager