136 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			136 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace Spark\Environment;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								use Psr\Log\LoggerAwareInterface;
							 | 
						||
| 
								 | 
							
								use Psr\Log\LoggerAwareTrait;
							 | 
						||
| 
								 | 
							
								use Spark\SparkApplication;
							 | 
						||
| 
								 | 
							
								use Symfony\Component\Console\Input\InputInterface;
							 | 
						||
| 
								 | 
							
								use Symfony\Component\Console\Output\OutputInterface;
							 | 
						||
| 
								 | 
							
								use Symfony\Component\Console\Style\SymfonyStyle;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class Environment
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    private bool $loaded = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    private array $config;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function __construct(array $config)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $this->config = $config;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function getProjectDirectory(): string
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return $this->config['project_dir'];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function getConfigDirectory(): string
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return $this->config['config_dir'];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function getDefinedScripts(): array
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return array_keys($this->config['scripts']??[]);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function runScript(string $name, array $args, InputInterface $input, OutputInterface $output)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $script = $this->config['scripts'][$name];
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        if (is_string($script)) {
							 | 
						||
| 
								 | 
							
								            // call script directly
							 | 
						||
| 
								 | 
							
								            if (str_ends_with($script, '.php')) {
							 | 
						||
| 
								 | 
							
								                $GLOBALS['args'] = $args;
							 | 
						||
| 
								 | 
							
								                $GLOBALS['output'] = $output;
							 | 
						||
| 
								 | 
							
								                $base = $this->getProjectDirectory();
							 | 
						||
| 
								 | 
							
								                if (!file_exists($base ."/". $script)) {
							 | 
						||
| 
								 | 
							
								                    fprintf(STDERR, "error: Could not find script file %s\n", $base."/".$script);
							 | 
						||
| 
								 | 
							
								                    return;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                include $base . "/" . $script;
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                passthru($script);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function loadEnvironment()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if ($this->loaded) {
							 | 
						||
| 
								 | 
							
								            return;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (!array_key_exists('project_dir', $this->config)) {
							 | 
						||
| 
								 | 
							
								            return;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // $this->logger->info("Loading environment...");
							 | 
						||
| 
								 | 
							
								        $preloads = [];
							 | 
						||
| 
								 | 
							
								        $root = $this->config['project_dir'];
							 | 
						||
| 
								 | 
							
								        foreach ((array)$this->config['preload']??[] as $preload) {
							 | 
						||
| 
								 | 
							
								            if (str_contains($preload,'*')) {
							 | 
						||
| 
								 | 
							
								                array_push($preloads, ...glob($root."/".$preload));
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                array_push($preloads, $preload);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        foreach ($preloads as $item) {
							 | 
						||
| 
								 | 
							
								            if (!str_starts_with($item, "/")) {
							 | 
						||
| 
								 | 
							
								                $item = $this->getProjectDirectory() . "/" . $item;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            if (is_file($item)) {
							 | 
						||
| 
								 | 
							
								                // $this->logger->debug("Preloading file {$item}");
							 | 
						||
| 
								 | 
							
								                try {
							 | 
						||
| 
								 | 
							
								                    include_once($item);
							 | 
						||
| 
								 | 
							
								                } catch (\Throwable $t) {
							 | 
						||
| 
								 | 
							
								                    fprintf(STDERR, "error: Error preloading %s: %s in %s on line %d\n", $item,  $t->getMessage(), $t->getFile(), $t->getLine());
							 | 
						||
| 
								 | 
							
								                    //$this->logger->error("Error preloading {$item}: {$t->getMessage()} in {$t->getFile()} on line {$t->getLine()}");
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            } elseif (is_dir($item) && file_exists($item."/sparkplug.php")) {
							 | 
						||
| 
								 | 
							
								                //$this->logger->debug("Preloading plugin {$item}");
							 | 
						||
| 
								 | 
							
								                try {
							 | 
						||
| 
								 | 
							
								                    include_once($item."/sparkplug.php");
							 | 
						||
| 
								 | 
							
								                } catch (\Throwable $t) {
							 | 
						||
| 
								 | 
							
								                    fprintf(STDERR, "error: Error preloading plugin %s: %s in %s on line %d\n", $item,  $t->getMessage(), $t->getFile(), $t->getLine());
							 | 
						||
| 
								 | 
							
								                    //$this->logger->error("Error preloading plugin {$item}: {$t->getMessage()} in {$t->getFile()} on line {$t->getLine()}");
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                fprintf(STDERR, "warning: Could not preload %s\n", $item);
							 | 
						||
| 
								 | 
							
								                //$this->logger->warning("Could not preload {$item}");
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        SparkApplication::$instance->getPluginManager()->initializePlugins();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public static function createFromDirectory(string|null $directory=null): Environment
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $directory = $directory ?? getcwd();
							 | 
						||
| 
								 | 
							
								        $candidates = [ $directory . "/.spark.json", $directory . "/.spark/spark.json" ];
							 | 
						||
| 
								 | 
							
								        $config = [];
							 | 
						||
| 
								 | 
							
								        while ($candidate = array_shift($candidates)) {
							 | 
						||
| 
								 | 
							
								            if (!file_exists($candidate)) { continue; }
							 | 
						||
| 
								 | 
							
								            $json = file_get_contents($candidate);
							 | 
						||
| 
								 | 
							
								            if (!$json || json_last_error()) {
							 | 
						||
| 
								 | 
							
								                throw new \RuntimeException("Error parsing {$candidate}: ".json_last_error_msg());
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            $config = json_decode($json, true);
							 | 
						||
| 
								 | 
							
								            $config['project_dir'] = realpath($directory);
							 | 
						||
| 
								 | 
							
								            $config['config_dir'] = realpath($directory)."/.spark";
							 | 
						||
| 
								 | 
							
								            $config['config_file'] = $candidate;
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $env = new Environment($config);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return $env;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 |