site = $site; $this->state = $state; $this->moduleHandler = $moduleHandler; $this->postUpdateRegistry = $postUpdateRegistry; $this->extensionManager = $extensionManager; $this->chainQueue = $chainQueue; parent::__construct(); } /** * @inheritdoc */ protected function configure() { $this ->setName('update:execute') ->setDescription($this->trans('commands.update.execute.description')) ->addArgument( 'module', InputArgument::OPTIONAL, $this->trans('commands.common.options.module'), 'all' ) ->addArgument( 'update-n', InputArgument::OPTIONAL, $this->trans('commands.update.execute.options.update-n'), '9000' ) ->setAliases(['upex']); } /** * @inheritdoc */ protected function execute(InputInterface $input, OutputInterface $output) { $this->module = $input->getArgument('module'); $this->update_n = (int)$input->getArgument('update-n'); $this->site->loadLegacyFile('/core/includes/install.inc'); $this->site->loadLegacyFile('/core/includes/update.inc'); drupal_load_updates(); update_fix_compatibility(); $start = $this->getUpdates($this->module!=='all'?$this->module:null); $updates = update_resolve_dependencies($start); $dependencyMap = []; foreach ($updates as $function => $update) { $dependencyMap[$function] = !empty($update['reverse_paths']) ? array_keys($update['reverse_paths']) : []; } if (!$this->checkUpdates($start, $updates)) { if ($this->module === 'all') { $this->getIo()->warning( sprintf( $this->trans( 'commands.update.execute.messages.no-pending-updates' ) ) ); } else { $this->getIo()->warning( sprintf( $this->trans( 'commands.update.execute.messages.no-module-updates' ), $this->module ) ); } return 0; } $maintenanceMode = $this->state->get('system.maintenance_mode', false); if (!$maintenanceMode) { $this->getIo()->info($this->trans('commands.site.maintenance.description')); $this->state->set('system.maintenance_mode', true); } try { $this->runUpdates( $updates ); // Post Updates are only safe to run after all schemas have been updated. if (!$this->getUpdates()) { $this->runPostUpdates(); } } catch (\Exception $e) { watchdog_exception('update', $e); $this->getIo()->error($e->getMessage()); return 1; } if (!$maintenanceMode) { $this->state->set('system.maintenance_mode', false); $this->getIo()->info($this->trans('commands.site.maintenance.messages.maintenance-off')); } if (!$this->getUpdates()) { $this->chainQueue->addCommand('update:entities'); } $this->chainQueue->addCommand('cache:rebuild', ['cache' => 'all']); return 0; } /** * @param array $start * @param array $updates * * @return bool true if the selected module/update number exists. */ private function checkUpdates( array $start, array $updates ) { if (!$start || !$updates) { return false; } if ($this->module !== 'all') { $module = $this->module; $hooks = array_keys($updates); $hooks = array_map( function ($v) use ($module) { return (int)str_replace( $module.'_update_', '', $v ); }, $hooks ); if ((int)min($hooks) > (int)$this->update_n) { return false; } } return true; } /** * @param array $updates */ private function runUpdates( array $updates ) { $this->getIo()->info( $this->trans('commands.update.execute.messages.executing-required-previous-updates') ); foreach ($updates as $function => $update) { if (!$update['allowed']) { continue; } if ($this->module !== 'all' && $update['number'] > $this->update_n) { break; } $this->getIo()->comment( sprintf( $this->trans('commands.update.execute.messages.executing-update'), $update['number'], $update['module'] ) ); $this->moduleHandler->loadInclude($update['module'], 'install'); $this->executeUpdate( $function, $context ); drupal_set_installed_schema_version( $update['module'], $update['number'] ); } } /** * @return bool */ private function runPostUpdates() { $postUpdates = $this->postUpdateRegistry->getPendingUpdateInformation(); foreach ($postUpdates as $module => $updates) { foreach ($updates['pending'] as $updateName => $update) { $this->getIo()->info( sprintf( $this->trans('commands.update.execute.messages.executing-update'), $updateName, $module ) ); $function = sprintf( '%s_post_update_%s', $module, $updateName ); drupal_flush_all_caches(); $this->executeUpdate( $function, $context ); $this->postUpdateRegistry->registerInvokedUpdates([$function]); } } return true; } protected function getUpdates($module = null) { $start = $this->getUpdateList(); if ($module) { if (isset($start[$module])) { $start = [ $module => $start[$module] ]; } else { $start = []; } } return $start; } // Copy of protected \Drupal\system\Controller\DbUpdateController::getModuleUpdates. protected function getUpdateList() { $start = []; $updates = update_get_update_list(); foreach ($updates as $module => $update) { $start[$module] = $update['start']; } return $start; } private function executeUpdate($function, &$context) { if (!$context || !array_key_exists('sandbox', $context)) { $context['sandbox'] = []; } if (function_exists($function)) { $function($context['sandbox']); } return true; } }