container = $container; } /** * Execute the post-upgrade actions */ public function execute() { // Do not execute the post-upgrade script in the development environment $realPath = realpath(__DIR__); if (@file_exists($realPath . '/../../.nopostupgrade')) { return; } // Special handling for running the Solo application inside WordPress. if ($this->container->segment->get('insideCMS', false)) { if (defined('WPINC')) { $this->_WordPressActions(); } } // Remove obsolete files $this->processRemoveFiles(); // Remove obsolete folders $this->processRemoveFolders(); // Migrate profiles $this->migrateProfiles(); // Migrate front-end API activation options $this->upgradeFrontendEnable(); } /** * Removes obsolete files, depending on the edition (core or pro) */ protected function processRemoveFiles() { $removeFiles = $this->removeFilesAllVersions; if (defined('AKEEBABACKUP_PRO') && AKEEBABACKUP_PRO) { $removeFiles = array_merge($removeFiles, $this->removeFilesPro); } else { $removeFiles = array_merge($removeFiles, $this->removeFilesCore); } $this->_removeFiles($removeFiles); } /** * Removes obsolete folders, depending on the edition (core or pro) */ protected function processRemoveFolders() { $removeFolders = $this->removeFoldersAllVersions; if (defined('AKEEBABACKUP_PRO') && AKEEBABACKUP_PRO) { $removeFolders = array_merge($removeFolders, $this->removeFoldersPro); } else { $removeFolders = array_merge($removeFolders, $this->removeFoldersCore); } $this->_removeFolders($removeFolders); } /** * Specific actions to execute when we are running inside WordPress */ private function _WordPressActions() { $this->_WordPressUpgradeToUtf8mb4(); $this->_WordPressRemoveFolders(); $this->_WordPressRemoveFiles(); } /** * Remove obsolete folders from the WordPress installation * * @return void */ private function _WordPressRemoveFolders() { $removeFolders = [ // Standalone platform 'app/Solo/Platform', // Obsolete folders after the introduction of Akeeba Engine 2 'helpers/platform/solowp', ]; // Remove WordPress-specific features from the Core release if (defined('AKEEBABACKUP_PRO') && !AKEEBABACKUP_PRO) { $removeFolders = array_merge([ 'helpers/assets/mu-plugins', 'wpcli' ], $removeFolders); } $fsBase = rtrim($this->container->filesystemBase, '/' . DIRECTORY_SEPARATOR) . '/../'; $fs = $this->container->fileSystem; foreach ($removeFolders as $folder) { $fs->rmdir($fsBase . $folder, true); } } /** * Remove obsolete files from the WordPress installation * * @return void */ private function _WordPressRemoveFiles() { $removeFiles = [ // Migrating INI files to .json files "helpers/Platform/Wordpress/Config/04.quota.ini", "helpers/Platform/Wordpress/Config/02.advanced.ini", "helpers/Platform/Wordpress/Config/Pro/04.quota.ini", "helpers/Platform/Wordpress/Config/Pro/02.advanced.ini", "helpers/Platform/Wordpress/Config/Pro/01.basic.ini", "helpers/Platform/Wordpress/Config/Pro/02.platform.ini", "helpers/Platform/Wordpress/Config/Pro/03.filters.ini", "helpers/Platform/Wordpress/Config/Pro/05.tuning.ini", "helpers/Platform/Wordpress/Config/01.basic.ini", "helpers/Platform/Wordpress/Config/02.platform.ini", "helpers/Platform/Wordpress/Config/05.tuning.ini", ]; // Remove WordPress-specific features from the Core release if (defined('AKEEBABACKUP_PRO') && !AKEEBABACKUP_PRO) { $additionalFiles = [ 'helpers/boot_wpcli.php', ]; $removeFiles = array_merge($removeFiles, $additionalFiles); } if (empty($removeFiles)) { return; } $fsBase = rtrim($this->container->filesystemBase, '/' . DIRECTORY_SEPARATOR) . '/../'; $fs = $this->container->fileSystem; foreach ($removeFiles as $file) { $fs->delete($fsBase . $file); } } /** * Update WordPress tables to utf8mb4 if required */ private function _WordPressUpgradeToUtf8mb4() { /** @var wpdb $wpdb */ global $wpdb; // Is it really WordPress? if (!is_object($wpdb)) { return; } // Is it really WordPress? if (!method_exists($wpdb, 'has_cap')) { return; } // Does the database support utf8mb4 at all? if (!$wpdb->has_cap('utf8mb4')) { return; } // Is the actual charset set to utf8mb4? $charset = strtolower($wpdb->charset); if ($charset != 'utf8mb4') { return; } // OK, all conditions met, let's upgrade the tables to utf8mb4 $dbInstaller = new Installer($this->container); $dbInstaller->setForcedFile($this->container->basePath . '/assets/sql/xml/utf8mb4_update.xml'); $dbInstaller->updateSchema(); return; } /** * Removes obsolete files given on a list * * @param array $removeFiles List of files to remove * * @return void */ private function _removeFiles(array $removeFiles) { if (empty($removeFiles)) { return; } $fsBase = rtrim($this->container->filesystemBase, '/' . DIRECTORY_SEPARATOR) . '/'; $fs = $this->container->fileSystem; foreach ($removeFiles as $file) { $fs->delete($fsBase . $file); } } /** * Removes obsolete folders given on a list * * @param array $removeFolders List of folders to remove * * @return void */ private function _removeFolders(array $removeFolders) { if (empty($removeFolders)) { return; } $fsBase = rtrim($this->container->filesystemBase, '/' . DIRECTORY_SEPARATOR) . '/'; $fs = $this->container->fileSystem; foreach ($removeFolders as $folder) { $fs->rmdir($fsBase . $folder, true); } } /** * Migrates existing backup profiles. The changes currently made are: * – Change post-processing from "s3" (legacy) to "amazons3" (current version) * – Fix profiles with invalid embedded installer settings * * @return void */ private function migrateProfiles() { // Get a list of backup profiles $db = $this->container->db; $query = $db->getQuery(true) ->select($db->qn('id')) ->from($db->qn('#__ak_profiles')); $profiles = $db->setQuery($query)->loadColumn(); // Normally this should never happen as we're supposed to have at least profile #1 if (empty($profiles)) { return; } // Migrate each profile foreach ($profiles as $profile) { // Initialization $dirty = false; // Load the profile configuration \Akeeba\Engine\Platform::getInstance()->load_configuration($profile); $config = \Akeeba\Engine\Factory::getConfiguration(); // -- Migrate obsolete "s3" engine to "amazons3" $postProcType = $config->get('akeeba.advanced.postproc_engine', ''); if ($postProcType == 's3') { $config->setKeyProtection('akeeba.advanced.postproc_engine', false); $config->setKeyProtection('engine.postproc.amazons3.signature', false); $config->setKeyProtection('engine.postproc.amazons3.accesskey', false); $config->setKeyProtection('engine.postproc.amazons3.secretkey', false); $config->setKeyProtection('engine.postproc.amazons3.usessl', false); $config->setKeyProtection('engine.postproc.amazons3.bucket', false); $config->setKeyProtection('engine.postproc.amazons3.directory', false); $config->setKeyProtection('engine.postproc.amazons3.rrs', false); $config->setKeyProtection('engine.postproc.amazons3.customendpoint', false); $config->setKeyProtection('engine.postproc.amazons3.legacy', false); $config->set('akeeba.advanced.postproc_engine', 'amazons3'); $config->set('engine.postproc.amazons3.signature', 's3'); $config->set('engine.postproc.amazons3.accesskey', $config->get('engine.postproc.s3.accesskey')); $config->set('engine.postproc.amazons3.secretkey', $config->get('engine.postproc.s3.secretkey')); $config->set('engine.postproc.amazons3.usessl', $config->get('engine.postproc.s3.usessl')); $config->set('engine.postproc.amazons3.bucket', $config->get('engine.postproc.s3.bucket')); $config->set('engine.postproc.amazons3.directory', $config->get('engine.postproc.s3.directory')); $config->set('engine.postproc.amazons3.rrs', $config->get('engine.postproc.s3.rrs')); $config->set('engine.postproc.amazons3.customendpoint', $config->get('engine.postproc.s3.customendpoint')); $config->set('engine.postproc.amazons3.legacy', $config->get('engine.postproc.s3.legacy')); $dirty = true; } // Fix profiles with invalid embedded installer settings $embeddedInstaller = $config->get('akeeba.advanced.embedded_installer'); if (empty($embeddedInstaller) || ($embeddedInstaller == 'angie-joomla') || ( (substr($embeddedInstaller, 0, 5) != 'angie') && ($embeddedInstaller != 'none') )) { $config->setKeyProtection('akeeba.advanced.embedded_installer', false); $config->set('akeeba.advanced.embedded_installer', 'angie'); $dirty = true; } // Save dirty records if ($dirty) { \Akeeba\Engine\Platform::getInstance()->save_configuration($profile); } } } /** * Upgrades the frontend_enable option into the two separate legacyapi_enabled and jsonapi_enabled options. * * Before version 7 we had a single option to control both frontend backup APIs. Starting version 7 we can enable * and disable them separately. */ public function upgradeFrontendEnable() { $currentValue = $this->container->appConfig->get('options.frontend_enable', null); if (is_null($currentValue)) { return; } $this->container->appConfig->set('options.frontend_enable', null); $this->container->appConfig->set('options.legacyapi_enabled', $currentValue); $this->container->appConfig->set('options.jsonapi_enabled', $currentValue); $this->container->appConfig->saveConfiguration(); } }