* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Mage; use Mage\Command\Factory; use Mage\Command\RequiresEnvironment; use Mage\Console\Colors; use Exception; use RecursiveDirectoryIterator; use SplFileInfo; /** * Magallanes interface between the Tasks and Commands and the User's Console. * * @author Andrés Montañez */ class Console { /** * @var array */ public static $paramsNotRequiringEnvironment = array('install' => 'install', 'upgrade' => 'upgrade', 'version' => 'version'); /** * Handler to the current Log File. * @var mixed */ private static $log = null; /** * The current logfile * @var string */ private static $logFile = null; /** * Enables or Disables Logging * @var boolean */ private static $logEnabled = true; /** * Enables or disables verbose logging * @var boolean */ private static $verboseLogEnabled = false; /** * String Buffer for the screen output * @var string */ private static $screenBuffer = ''; /** * Output of executed commands * @var string */ private static $commandsOutput = ''; /** * Configuration * @var \Mage\Config */ private static $config; /** * Runns a Magallanes Command * @throws Exception */ public function run($arguments) { $exitCode = 10; // Declare a Shutdown Closure register_shutdown_function(function () { // Only Unlock if there was an error if (error_get_last() !== null) { if (file_exists(getcwd() . '/.mage/~working.lock')) { unlink(getcwd() . '/.mage/~working.lock'); } } }); $config = self::$config = new Config; $configError = false; try { // Load configuration $config->load($arguments); } catch (Exception $exception) { $configError = $exception->getMessage(); } // Command Option $commandName = $config->getArgument(0); // Logging $showGreetings = true; if (in_array($commandName, self::$paramsNotRequiringEnvironment)) { self::$logEnabled = false; $showGreetings = false; } else { self::$logEnabled = $config->general('logging', false); } self::$verboseLogEnabled = self::isVerboseLoggingEnabled(); // Greetings if ($showGreetings) { if (!self::$logEnabled) { self::output('Starting Magallanes', 0, 2); } else { self::output('Starting Magallanes', 0, 1); self::log("Logging enabled"); self::output('Logging enabled: ' . self::getLogFile() . '', 1, 2); } } // Run Command - Check if there is a Configuration Error if ($configError !== false) { self::output('' . $configError . '', 1, 2); } else { // Run Command and check for Command Requirements try { $command = Factory::get($commandName, $config); if ($config->getParameter('help')) { self::output($command->getInfoMessage(), 2); return 0; } if ($command instanceof RequiresEnvironment && $config->getEnvironment() === false) { throw new Exception('You must specify an environment for this command.'); } // Run the Command $exitCode = $command->run(); // Check for errors if (is_int($exitCode) && $exitCode !== 0) { throw new Exception('Command execution failed with following exit code: ' . $exitCode, $exitCode); } elseif (is_bool($exitCode) && !$exitCode) { $exitCode = 1; throw new Exception('Command execution failed.', $exitCode); } } catch (Exception $exception) { self::output('' . $exception->getMessage() . '', 1, 2); } } if ($showGreetings) { self::output('Finished Magallanes', 0, 2); if (file_exists(getcwd() . '/.mage/~working.lock')) { unlink(getcwd() . '/.mage/~working.lock'); } } // Check if logs need to be deleted self::checkLogs($config); return $exitCode; } /** * Outputs a message to the user's screen. * * @param string $message * @param integer $tabs * @param integer $newLine */ public static function output($message, $tabs = 1, $newLine = 1) { self::log(strip_tags($message)); if (!self::$verboseLogEnabled) { self::$screenBuffer .= str_repeat("\t", $tabs) . strip_tags($message) . str_repeat(PHP_EOL, $newLine); $output = str_repeat("\t", $tabs) . Colors::color($message, self::$config) . str_repeat(PHP_EOL, $newLine); echo $output; } } /** * Executes a Command on the Shell * * @param string $command * @param string $output * @return boolean */ public static function executeCommand($command, &$output = null) { self::log('---------------------------------'); self::log('---- Executing: $ ' . $command); $return = 1; $log = array(); exec($command . ' 2>&1', $log, $return); $log = implode(PHP_EOL, $log); if (!$return) { $output = trim($log); } self::$commandsOutput .= PHP_EOL . trim($log) . PHP_EOL; self::log($log); self::log('---------------------------------'); return !$return; } /** * Log a message to the logfile. * * @param string $message */ public static function log($message) { if (self::$logEnabled) { if (self::$log === null) { self::$logFile = realpath(getcwd() . '/.mage/logs') . '/log-' . date('Ymd-His') . '.log'; self::$log = fopen(self::$logFile, 'w'); } $message = date('Y-m-d H:i:s -- ') . $message; fwrite(self::$log, $message . PHP_EOL); if (self::$verboseLogEnabled) { echo $message . PHP_EOL; } } } /** * Return the screen buffer * @return string */ public static function getOutput() { return self::$screenBuffer; } /** * Returns the Log File * @return string */ public static function getLogFile() { return self::$logFile; } /** * Read String From Prompt */ public static function readInput() { $fp = fopen("php://stdin", "r"); $line = fgets($fp); return rtrim($line); } /** * Check Logs * @param \Mage\Config $config */ private static function checkLogs(Config $config) { if (self::$logEnabled) { $maxLogs = $config->general('maxlogs', 30); $logs = array(); foreach (new RecursiveDirectoryIterator(getcwd() . '/.mage/logs', RecursiveDirectoryIterator::SKIP_DOTS) as $log) { /* @var $log SplFileInfo */ if (strpos($log->getFilename(), 'log-') === 0) { $logs[] = $log->getFilename(); } } sort($logs); if (count($logs) > $maxLogs) { $logsToDelete = array_slice($logs, 0, count($logs) - $maxLogs); foreach ($logsToDelete as $logToDeelte) { unlink(getcwd() . '/.mage/logs/' . $logToDeelte); } } } } /** * Check if verbose logging is enabled * @return boolean */ protected static function isVerboseLoggingEnabled() { return self::$config->getParameter('verbose', false) || self::$config->general('verbose_logging') || self::$config->environmentConfig('verbose_logging', false); } }