BigDbCli.php

<?php

namespace Tlf\BigDb;

/**
 * BigDb's own CLI, for setting up BigDb libraries.
 */
class BigDbCli extends \Tlf\Cli {


    protected array $config = [];

    protected \PDO $pdo;

    public function __construct(){
        parent::__construct();

    }

    /**
     * add commands to cli
     */
    public function init(){
        $cli = $this;
        $call = [$cli, 'call'];


        $cli->load_command('main',
            function($cli, $args){
                $cli->call_command('help',[]);
            }, "show this help menu"
        );

        $cli->exclude_from_help[] = 'main';

        $cli->load_command('create-bin', $call, "Create cli script for your BigDb library.");
    }

    /**
     * Setup config / database credentials
     *
     * @param $args array - not used
     * @param $named_args array - not used
     */
    public function cmd_create_bin(array $args, array $named_args){

        $cli = $this;

        $config_rel_path = $cli->prompt("Choose relative config file location (json)");


        $cfg_dir = dirname($config_rel_path);
        $cfg_dir_path = getcwd().'/'.$cfg_dir;

        $config_path = $cli->pwd.'/'.$config_rel_path;
        if (!file_exists($config_path)){
            $make = $cli->ask("Create $config_rel_path");
        } else {
            $make = $cli->ask("Overwrite $config_rel_path");
        }
        if (!$make){
            echo "\n\nConfig file generation skipped.\n\n";
            goto skip_config_make;
        }

        if (!is_dir($cfg_dir_path)){
            mkdir($cfg_dir_path, 0754);
        }

        $app_class = $cli->prompt("BigDb Subclass (recommended)");
        if ($app_class==null){
            $app_class = \Tlf\BigDb::class;
            echo "  Using $app_class\n";
        }

        $app_dir = $cli->prompt("BigDb App Dir (relative to current dir)");

        $host = $cli->prompt("MySql Host");
        $database = $cli->prompt("MySql Database");
        $user = $cli->prompt("MySql User");
        // @TODO hide user input when prompting for mysql password
        $password = $cli->prompt("MySql Password");

        file_put_contents($config_path, 
            json_encode(
                [ 
                  'app.class'=>$app_class,
                  'app.dir'=> $app_dir,
                  'mysql.host'=>$host,
                  'mysql.database'=>$database,
                  'mysql.user' => $user,
                  'mysql.password' => $password,
                ],
                JSON_PRETTY_PRINT
            )
        );

        skip_config_make:

        $ignore = $cli->ask("Add $config_rel_path to .gitignore");
        if ($ignore){
            $ignore_file = getcwd().'/.gitignore';
            $fh = fopen($ignore_file, 'a');
            try {
                fwrite($fh, "\n$config_rel_path");
            } 
            catch (\Exception $e){} 
            finally {
                fclose($fh);
            }
        }


        $bin_path = $this->get_bin_file_path();
        if ($bin_path==''){
            echo "\n\nERROR: invalid bin file path\n\n";
            return;
        }

        if (!is_dir($bin_dir = dirname($bin_path))){
            mkdir($bin_dir, 0754, true);
        }

        $bin_sample = file_get_contents(__DIR__.'/bigdb-sample-cli');
        $bin_final = str_replace("CONFIG_FILE_LOCATION", $config_rel_path, $bin_sample);

        file_put_contents($bin_path, $bin_final);

        echo "\n\nYou may need to add EXECUTE permissions to the bin file.\n\n";


    }


    /**
     * Get path to app dir, relative to the librarys root dir
     *
     * @param return string relative path to app directory. 
     */
    public function get_app_dir(): string {

        $app_dir = $this->prompt("Relative path to your bigdb app dir [blank for src/db]");
        $app_dir = trim($app_dir);
        $path = $this->pwd.'/'.$app_dir;
        if (file_exists($app_dir) && !is_dir($app_dir)){
            echo "\n\nNOTICE: File exists at '$app_dir'\n\n";
        } else if (!file_exists($app_dir)){
            echo "\n\nNOTICE: Directory '$app_dir' does not exist\n\n";
        }

        return $app_dir;
    }

    /**
     *
     * @param return string BigDb subclass for your app
     */
    public function get_app_class(): string {
        $app_class = '';

        get_class:

        $app_class = $this->prompt("BigDb class/subclass [blank for \Tlf\BigDb]");
        $app_class = trim($app_class);
        if ($app_class == ''){
            $app_class = \Tlf\BigDb\Defaults::APP_CLASS;
        }
        if (!class_exists($app_class)){
            echo "Class '$app_class' does not exist";
            $create_anyway = $this->ask("Configure BigDb class '$app_class' anyway");
            if ($create_anyway)return $app_class;
            else goto get_class;
        }         
        
        return $app_class;

    }

    /**
     *
     * @param return string absolute path to destination bin path or empty string on failure
     */
    public function get_bin_file_path(): string {
        $bin_location = $this->prompt("Relative path to bin script [ex: bin/library-name]");
        $bin_location = trim($bin_location);
        $path = $this->pwd.'/'.$bin_location;
        if (is_file($bin_location)){
            echo "\n\nWARNING! Bin file will be overwritten: $bin_location\n\n";
            $should_overwrite = $this->ask("Overwrite bin script");
            if (!$should_overwrite)die("\n");
        }         

        return $path;
    }

    /**
     *
     * @param return string absolute path to destination config path
     */
    public function get_config_file_path(): string {
        $config_location = $this->prompt("Relative config file path [blank for 'config/bigdb.json']");
        $config_location = trim($config_location);
        if ($config_location == ''){
            $config_location = \Tlf\BigDb\Defaults::CONFIG_FILE_LOCATION;
        }
        $path = $this->pwd.'/'.$config_location;
        if (is_file($config_location)){
            echo "\n\nWARNING! Config file will be overwritten: $config_location\n\n";

            $should_overwrite = $this->ask("Overwrite config file");
            if (!$should_overwrite)die("\n");
        }         

        return $path;
    }

    /**
     * Call a cli command
     * @param $cli arg not used, because it should always be this object
     * @param $args array of args, with $args['--'] containing unnamed args.
     */
    public function call(\Tlf\BigDb\BigDbCli $cli, array $args){
        // SETUP
        $command = $this->command;
        $unnamed_args = $args['--'] ?? [];
        unset($args['--']);

        $func = 'cmd_'.str_replace('-','_',$command);
        if (!method_exists($this, $func)){
            echo "\nCommand '$command' does not exist\n";
            return;
        }

        // RUN
        echo "\n";
        $this->$func($unnamed_args, $args);
        echo "\n";
    }

    
}