* @author Jörn Friedrich Dreyer * @author Lukas Reschke * @author Miha Frangez * @author Morris Jobke * @author noveens * @author Robin Appelman * @author Thomas Müller * @author Victor Dubiniuk * * @license AGPL-3.0 * * This code is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License, version 3, * along with this program. If not, see * */ namespace OCA\OCCWeb\Controller; //use OC\MemoryInfo; use OC\NeedsUpdateException; use OC_App; use OCP\AppFramework\QueryException; use OCP\Console\ConsoleEvent; use OCP\IConfig; use OCP\ILogger; use Symfony\Component\Console\Application as SymfonyApplication; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; class OCCApplication { /** @var IConfig */ private $config; /** @var EventDispatcherInterface */ private $dispatcher; /** @var ILogger */ private $logger; // /** @var MemoryInfo */ // private $memoryInfo; /** * @param IConfig $config * @param EventDispatcherInterface $dispatcher * @param ILogger $logger * @param MemoryInfo $memoryInfo */ public function __construct(IConfig $config, EventDispatcherInterface $dispatcher, ILogger $logger/*, MemoryInfo $memoryInfo*/) { $defaults = \OC::$server->getThemingDefaults(); $this->config = $config; $this->application = new SymfonyApplication($defaults->getName(), \OC_Util::getVersionString()); $this->dispatcher = $dispatcher; $this->logger = $logger; // $this->memoryInfo = $memoryInfo; } /** * @param InputInterface $input * @param ConsoleOutputInterface $output * @throws \Exception */ public function loadCommands( InputInterface $input, ConsoleOutputInterface $output ) { // $application is required to be defined in the register_command scripts $application = $this->application; $inputDefinition = $application->getDefinition(); $inputDefinition->addOption( new InputOption( 'no-warnings', null, InputOption::VALUE_NONE, 'Skip global warnings, show command output only', null ) ); try { $input->bind($inputDefinition); } catch (\RuntimeException $e) { //expected if there are extra options } if ($input->getOption('no-warnings')) { $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); } // if ($this->memoryInfo->isMemoryLimitSufficient() === false) { // $output->getErrorOutput()->writeln( // 'The current PHP memory limit ' . // 'is below the recommended value of 512MB.' // ); // } try { require_once __DIR__ . '/../../../../core/register_command.php'; if ($this->config->getSystemValue('installed', false)) { if (\OCP\Util::needUpgrade()) { throw new NeedsUpdateException(); } elseif ($this->config->getSystemValue('maintenance', false)) { $this->writeMaintenanceModeInfo($input, $output); } else { OC_App::loadApps(); foreach (\OC::$server->getAppManager()->getInstalledApps() as $app) { $appPath = \OC_App::getAppPath($app); if ($appPath === false) { continue; } // load commands using info.xml $info = \OC_App::getAppInfo($app); if (isset($info['commands'])) { $this->loadCommandsFromInfoXml($info['commands']); } // load from register_command.php \OC_App::registerAutoloading($app, $appPath); $file = $appPath . '/appinfo/register_command.php'; if (file_exists($file)) { try { require $file; } catch (\Exception $e) { $this->logger->logException($e); } } } } } else if ($input->getArgument('command') !== '_completion' && $input->getArgument('command') !== 'maintenance:install') { $output->writeln("Nextcloud is not installed - only a limited number of commands are available"); } } catch(NeedsUpdateException $e) { if ($input->getArgument('command') !== '_completion') { $output->writeln("Nextcloud or one of the apps require upgrade - only a limited number of commands are available"); $output->writeln("You may use your browser or the occ upgrade command to do the upgrade"); } } if ($input->getFirstArgument() !== 'check') { $errors = \OC_Util::checkServer(\OC::$server->getSystemConfig()); if (!empty($errors)) { foreach ($errors as $error) { $output->writeln((string)$error['error']); $output->writeln((string)$error['hint']); $output->writeln(''); } throw new \Exception("Environment not properly prepared."); } } } /** * Write a maintenance mode info. * The commands "_completion" and "maintenance:mode" are excluded. * * @param InputInterface $input The input implementation for reading inputs. * @param ConsoleOutputInterface $output The output implementation * for writing outputs. * @return void */ private function writeMaintenanceModeInfo( InputInterface $input, ConsoleOutputInterface $output ) { if ($input->getArgument('command') !== '_completion' && $input->getArgument('command') !== 'maintenance:mode') { $errOutput = $output->getErrorOutput(); $errOutput->writeln( 'Nextcloud is in maintenance mode - ' . 'no apps have been loaded' . PHP_EOL ); } } /** * Sets whether to automatically exit after a command execution or not. * * @param bool $boolean Whether to automatically exit after a command execution or not */ public function setAutoExit($boolean) { $this->application->setAutoExit($boolean); } /** * @param InputInterface $input * @param OutputInterface $output * @return int * @throws \Exception */ public function run(InputInterface $input = null, OutputInterface $output = null) { $this->dispatcher->dispatch(ConsoleEvent::EVENT_RUN, new ConsoleEvent( ConsoleEvent::EVENT_RUN, ['occ'] )); return $this->application->run($input, $output); } private function loadCommandsFromInfoXml($commands) { foreach ($commands as $command) { try { $c = \OC::$server->query($command); } catch (QueryException $e) { if (class_exists($command)) { $c = new $command(); } else { throw new \Exception("Console command '$command' is unknown and could not be loaded"); } } $this->application->add($c); } } }