File manager - Edit - /usr/local/lsws/add-ons/webcachemgr/src/WPInstallStorage.php
Back
<?php /** ********************************************* * LiteSpeed Web Server Cache Manager * * @author LiteSpeed Technologies, Inc. (https://www.litespeedtech.com) * @copyright (c) 2018-2021 * ******************************************* */ namespace Lsc\Wp; use Lsc\Wp\Context\Context; use Lsc\Wp\Panel\ControlPanel; /** * map to data file */ class WPInstallStorage { /** * @var string */ const CMD_ADD_CUST_WPINSTALLS = 'addCustWPInstalls'; /** * @since 1.13.3 * @var string */ const CMD_ADD_NEW_WPINSTALL = 'addNewWPInstall'; /** * @deprecated 1.13.3 Use CMD_DISCOVER_NEW2 instead. * @var string */ const CMD_DISCOVER_NEW = 'discoverNew'; /** * @since 1.13.3 * @var string */ const CMD_DISCOVER_NEW2 = 'discoverNew2'; /** * @var string */ const CMD_FLAG = 'flag'; /** * @var string */ const CMD_MASS_UNFLAG = 'mass_unflag'; /** * @deprecated 1.13.3 Use CMD_SCAN2 instead for now. * @var string */ const CMD_SCAN = 'scan'; /** * @since 1.13.3 * @var string */ const CMD_SCAN2 = 'scan2'; /** * @var string */ const CMD_UNFLAG = 'unflag'; /** * @var string */ const DATA_VERSION = '1.5'; /** * @var int */ const ERR_NOT_EXIST = 1; /** * @var int */ const ERR_CORRUPTED = 2; /** * @var int */ const ERR_VERSION_HIGH = 3; /** * @var int */ const ERR_VERSION_LOW = 4; /** * @var string */ protected $dataFile; /** * @var string */ protected $customDataFile; /** * @var null|WPInstall[] Key is path */ protected $wpInstalls = null; /** * @var null|WPInstall[] Key is path */ protected $custWpInstalls = null; /** * @var int */ protected $error; /** * @var WPInstall[] */ protected $workingQueue = array(); /** * * @param string $dataFile * @param string $custDataFile * @throws LSCMException Thrown indirectly. */ public function __construct( $dataFile, $custDataFile = '' ) { $this->dataFile = $dataFile; $this->customDataFile = $custDataFile; $this->error = $this->init(); } /** * * @return int * @throws LSCMException Thrown indirectly. */ protected function init() { $dataExists = false; try { if ( file_exists($this->dataFile) ) { $dataExists = true; $this->wpInstalls = $this->getDataFileData($this->dataFile); } if ( $this->customDataFile != '' && file_exists($this->customDataFile) ) { $dataExists = true; $this->custWpInstalls = $this->getDataFileData($this->customDataFile); } } catch ( LSCMException $e ) { Logger::debug($e->getMessage()); return $e->getCode(); } if ( !$dataExists ) { return self::ERR_NOT_EXIST; } return 0; } /** * * @param string $dataFile * @return WPInstall[] * @throws LSCMException Thrown indirectly. */ protected function getDataFileData( $dataFile ) { $content = file_get_contents($dataFile); if ( ($data = json_decode($content, true)) === null ) { /* * Data file may be in old serialized format. Try unserializing. */ $data = unserialize($content); } if ( $data === false || !is_array($data) || !isset($data['__VER__']) ) { throw new LSCMException( "$dataFile - Data is corrupt.", self::ERR_CORRUPTED ); } if ( ($err = $this->verifyDataFileVer($dataFile, $data['__VER__'])) ) { throw new LSCMException( "$dataFile - Data file version issue.", $err ); } unset($data['__VER__']); $wpInstalls = array(); foreach ( $data as $utf8Path => $idata ) { $path = utf8_decode($utf8Path); $i = new WPInstall($path); $idata[WPInstall::FLD_SITEURL] = urldecode($idata[WPInstall::FLD_SITEURL]); $idata[WPInstall::FLD_SERVERNAME] = urldecode($idata[WPInstall::FLD_SERVERNAME]); $i->initData($idata); $wpInstalls[$path] = $i; } return $wpInstalls; } /** * * @return int */ public function getError() { return $this->error; } /** * * @param bool $nonFatalOnly * @return int */ public function getCount( $nonFatalOnly = false ) { $count = 0; if ( !$nonFatalOnly ) { if ( $this->wpInstalls != null ) { $count += count($this->wpInstalls); } if ( $this->custWpInstalls != null ) { $count += count($this->custWpInstalls); } } else { foreach ( $this->wpInstalls as $install ) { if ( !$install->hasFatalError() ) { $count++; } } foreach ( $this->custWpInstalls as $custInstall ) { if ( !$custInstall->hasFatalError() ) { $count++; } } } return $count; } /** * * @return null|WPInstall[] * * @noinspection PhpUnused */ public function getWPInstalls() { return $this->wpInstalls; } /** * * @return null|WPInstall[] * * @noinspection PhpUnused */ public function getCustWPInstalls() { return $this->custWpInstalls; } /** * * @return null|WPInstall[] */ public function getAllWPInstalls() { if ( $this->wpInstalls != null ) { if ( $this->custWpInstalls != null ) { return array_merge($this->wpInstalls, $this->custWpInstalls); } else { return $this->wpInstalls; } } elseif ( $this->custWpInstalls != null ) { return $this->custWpInstalls; } else { return null; } } /** * Get all known WPInstall paths. * * @return string[] */ public function getPaths() { $paths = array(); if ( $this->wpInstalls != null ) { $paths = array_keys($this->wpInstalls); } if ( $this->custWpInstalls != null ) { $paths = array_merge($paths, array_keys($this->custWpInstalls)); } return $paths; } /** * * @param string $path * @return WPInstall|null */ public function getWPInstall( $path ) { if ( ($realPath = realpath($path)) === false ) { $index = $path; } else { $index = $realPath; } if ( isset($this->wpInstalls[$index]) ) { return $this->wpInstalls[$index]; } elseif ( isset($this->custWpInstalls[$index]) ) { return $this->custWpInstalls[$index]; } return null; } /** * * @return WPInstall[] */ public function getWorkingQueue() { return $this->workingQueue; } /** * * @param WPInstall $wpInstall */ public function addWPInstall( WPInstall $wpInstall ) { $this->wpInstalls[$wpInstall->getPath()] = $wpInstall; } /** * * @throws LSCMException Thrown indirectly. */ public function syncToDisk() { $this->saveDataFile($this->dataFile, $this->wpInstalls); if ( $this->customDataFile != '' ) { $this->saveDataFile($this->customDataFile, $this->custWpInstalls); } } /** * * @param string $dataFile * @param WPInstall[] $wpInstalls * @throws LSCMException Thrown indirectly. */ protected function saveDataFile( $dataFile, $wpInstalls ) { $data = array( '__VER__' => self::DATA_VERSION ); if ( !empty($wpInstalls) ) { foreach ( $wpInstalls as $path => $install ) { if ( !$install->shouldRemove() ) { $utf8Path = utf8_encode($path); $data[$utf8Path] = $install->getData(); $siteUrl = &$data[$utf8Path][WPInstall::FLD_SITEURL]; $siteUrl = urlencode($siteUrl); $serverName = &$data[$utf8Path][WPInstall::FLD_SERVERNAME]; $serverName = urlencode($serverName); } } ksort($data); } $file_str = json_encode($data); file_put_contents($dataFile, $file_str, LOCK_EX); chmod($dataFile, 0600); $this->log("Data file saved $dataFile", Logger::L_DEBUG); } /** * * @param string $dataFile * @param string $dataFileVer * @return int * @throws LSCMException Thrown indirectly. */ protected function verifyDataFileVer( $dataFile, $dataFileVer ) { $res = version_compare($dataFileVer, self::DATA_VERSION); if ( $res == 1 ) { Logger::info( 'Data file version is higher than expected and cannot be used.' ); return self::ERR_VERSION_HIGH; } if ( $res == -1 && !$this->updateDataFile($dataFile, $dataFileVer) ) { return self::ERR_VERSION_LOW; } return 0; } /** * * @param string $dataFile * @param string $dataFileVer * @return bool * @throws LSCMException Thrown indirectly. */ public static function updateDataFile( $dataFile, $dataFileVer ) { Logger::info( "$dataFile - Old data file version detected. Attempting to " . 'update...' ); /** * Currently no versions are upgradeable to 1.5 */ $updatableVersions = array(); if ( ! in_array($dataFileVer, $updatableVersions) || ! Util::createBackup($dataFile) ) { Logger::error( "$dataFile - Data file could not be updated to version " . self::DATA_VERSION ); return false; } /** * Upgrade funcs will be called here. */ return true; } /** * * @param string $action * @return string[] * @throws LSCMException Thrown indirectly. */ protected function prepareActionItems( $action ) { switch ($action) { case self::CMD_SCAN: case self::CMD_SCAN2: case self::CMD_DISCOVER_NEW: case self::CMD_DISCOVER_NEW2: try { return ControlPanel::getClassInstance()->getDocRoots(); } catch ( LSCMException $e ) { throw new LSCMException( $e->getMessage() . " Could not prepare $action action items." ); } case UserCommand::CMD_MASS_ENABLE: case UserCommand::CMD_MASS_DISABLE: case UserCommand::CMD_MASS_UPGRADE: case UserCommand::CMD_MASS_DASH_NOTIFY: case UserCommand::CMD_MASS_DASH_DISABLE: case self::CMD_MASS_UNFLAG: return $this->getPaths(); default: throw new LSCMException('Missing parameter(s).'); } } /** * * @param string $action * @param string $path * @param string[] $extraArgs * @throws LSCMException Thrown indirectly. */ protected function doWPInstallAction( $action, $path, $extraArgs ) { if ( ($wpInstall = $this->getWPInstall($path)) == null ) { $wpInstall = new WPInstall($path); $this->addWPInstall($wpInstall); } switch ($action) { case self::CMD_FLAG: if ( !$wpInstall->hasValidPath() ) { return; } if ( $wpInstall->addUserFlagFile(false) ) { $wpInstall->setCmdStatusAndMsg( UserCommand::EXIT_SUCC, 'Flag file set' ); } else { $wpInstall->setCmdStatusAndMsg( UserCommand::EXIT_FAIL, 'Could not create flag file' ); } $this->workingQueue[$path] = $wpInstall; return; case self::CMD_UNFLAG: case self::CMD_MASS_UNFLAG: if ( !$wpInstall->hasValidPath() ) { return; } $wpInstall->removeFlagFile(); $wpInstall->setCmdStatusAndMsg( UserCommand::EXIT_SUCC, 'Flag file unset' ); $this->workingQueue[$path] = $wpInstall; return; case UserCommand::CMD_ENABLE: case UserCommand::CMD_DISABLE: case UserCommand::CMD_DASH_NOTIFY: case UserCommand::CMD_DASH_DISABLE: if ( $wpInstall->hasFatalError() ) { $wpInstall->refreshStatus(); if ( $wpInstall->hasFatalError() ) { $wpInstall->addUserFlagFile(false); $wpInstall->setCmdStatusAndMsg( UserCommand::EXIT_FAIL, 'Install skipped and flagged due to Error status.' ); $this->workingQueue[$path] = $wpInstall; return; } } break; case UserCommand::CMD_MASS_UPGRADE: $allowedVers = PluginVersion::getInstance()->getAllowedVersions(); if ( !in_array($extraArgs[1], $allowedVers) ) { throw new LSCMException( 'Selected LSCWP version (' . htmlspecialchars($extraArgs[1]) . ') is invalid.' ); } break; //no default } if ( UserCommand::issue($action, $wpInstall, $extraArgs) ) { if ( $action == UserCommand::CMD_MASS_UPGRADE && ($wpInstall->getCmdStatus() & UserCommand::EXIT_FAIL) && preg_match('/Download failed. Not Found/', $wpInstall->getCmdMsg()) ) { $this->syncToDisk(); throw new LSCMException( 'Could not download version ' . htmlspecialchars($extraArgs[1]) . '.' ); } if ( $action == UserCommand::CMD_MASS_ENABLE && ($wpInstall->getCmdStatus() & UserCommand::EXIT_FAIL) && preg_match('/Source Package not available/', $wpInstall->getCmdMsg()) ) { $this->syncToDisk(); throw new LSCMException($wpInstall->getCmdMsg()); } $this->workingQueue[$path] = $wpInstall; } } /** * * @param string $action * @param null|string[] $list * @param string[]|string[][] $extraArgs * @return string[] * @throws LSCMException Thrown indirectly. */ public function doAction( $action, $list, $extraArgs = array() ) { if ( $list === null ) { $list = $this->prepareActionItems($action); } $count = count($list); $this->log("doAction {$action} for {$count} items", Logger::L_VERBOSE); $endTime = $count > 1 ? Context::getActionTimeout() : 0; $finishedList = array(); switch ( $action ) { case self::CMD_SCAN: case self::CMD_DISCOVER_NEW: $forceRefresh = ($action == self::CMD_SCAN); foreach ( $list as $path ) { $this->scan($path, $forceRefresh); $finishedList[] = $path; if ( $endTime && time() >= $endTime ) { break; } } break; case self::CMD_ADD_NEW_WPINSTALL: foreach ( $list as $path) { $this->addNewWPInstall($path); $finishedList[] = $path; if ( $endTime && time() >= $endTime ) { break; } } break; case self::CMD_ADD_CUST_WPINSTALLS: $wpInstallsInfo = $extraArgs[0]; $this->addCustomInstallations($wpInstallsInfo); break; default: if ( $action == UserCommand::CMD_ENABLE || $action == UserCommand::CMD_MASS_ENABLE ) { /** * Ensure that current version is locally downloaded. */ $currVer = PluginVersion::getCurrentVersion(); PluginVersion::getInstance()->setActiveVersion($currVer); } foreach ( $list as $path ) { $this->doWPInstallAction($action, $path, $extraArgs); $finishedList[] = $path; if ( $endTime && time() >= $endTime ) { break; } } } $this->syncToDisk(); if ( $action == self::CMD_SCAN || $action == self::CMD_SCAN2 ) { /** * Explicitly clear any data file errors after scanning in case of * multiple actions performed in the same process (cli). */ $this->error = 0; } return $finishedList; } /** * * @deprecated 1.13.3 Use $this->scan2() instead. * * @param string $docroot * @param bool $forceRefresh * @return void * @throws LSCMException Thrown indirectly. */ protected function scan( $docroot, $forceRefresh = false ) { $depth = Context::getScanDepth(); $cmd = "find -L $docroot -maxdepth $depth -name wp-admin -print"; $directories = shell_exec($cmd); /** * Example: * /home/user/public_html/wordpress/wp-admin * /home/user/public_html/blog/wp-admin * /home/user/public_html/wp/wp-admin */ $hasMatches = preg_match_all( "|$docroot(.*)(?=/wp-admin)|", $directories, $matches ); if ( ! $hasMatches ) { /** * Nothing found. */ return; } foreach ( $matches[1] as $path ) { $wp_path = realpath($docroot . $path); $refresh = $forceRefresh; if ( !isset($this->wpInstalls[$wp_path]) ) { $this->wpInstalls[$wp_path] = new WPInstall($wp_path); $refresh = true; $this->log( "New installation found: $wp_path", Logger::L_INFO ); if ( $this->custWpInstalls != null && isset($this->custWpInstalls[$wp_path]) ) { unset($this->custWpInstalls[$wp_path]); $this->log( "Installation removed from custom data file: $wp_path", Logger::L_INFO ); } } else { $this->log( "Installation already found: $wp_path", Logger::L_DEBUG ); } if ( $refresh ) { $this->wpInstalls[$wp_path]->refreshStatus(); $this->workingQueue[$wp_path] = $this->wpInstalls[$wp_path]; } } } /** * * @since 1.13.3 * * @param string $docroot * @return string[] * @throws LSCMException Thrown indirectly. */ public function scan2( $docroot ) { $depth = Context::getScanDepth(); $cmd = "find -L $docroot -maxdepth $depth -name wp-admin -print"; $directories = shell_exec($cmd); /** * Example: * /home/user/public_html/wordpress/wp-admin * /home/user/public_html/blog/wp-admin * /home/user/public_html/wp/wp-admin */ $hasMatches = preg_match_all( "|$docroot(.*)(?=/wp-admin)|", $directories, $matches ); if ( ! $hasMatches ) { /** * Nothing found. */ return array(); } $wpPaths = array(); foreach ( $matches[1] as $path ) { $wpPath = realpath($docroot . $path); $wpPaths[] = $wpPath; } return $wpPaths; } /** * Add a new WPInstall object to WPInstallStorage's $wpInstalls[] given a * path to a WordPress installation and refresh it's status . If a WPInstall * object already exists for the given path, refresh it's status. * * @since 1.13.3 * * @param string $wpPath * @throws LSCMException Thrown indirectly. */ protected function addNewWPInstall( $wpPath ) { if ( ($realPath = realpath($wpPath)) !== false ) { $wpPath = $realPath; } if ( !isset($this->wpInstalls[$wpPath]) ) { $this->wpInstalls[$wpPath] = new WPInstall($wpPath); $this->log("New installation found: $wpPath", Logger::L_INFO); if ( $this->custWpInstalls != null && isset($this->custWpInstalls[$wpPath]) ) { unset($this->custWpInstalls[$wpPath]); $this->log( "Installation removed from custom data file: $wpPath", Logger::L_INFO ); } } else { $this->log( "Installation already found: $wpPath", Logger::L_DEBUG ); } $this->wpInstalls[$wpPath]->refreshStatus(); $this->workingQueue[$wpPath] = $this->wpInstalls[$wpPath]; } /** * * @param string[] $wpInstallsInfo * @return void * @throws LSCMException Thrown indirectly. */ protected function addCustomInstallations( $wpInstallsInfo ) { if ( $this->customDataFile == '' ) { $this->log( 'No custom data file set, could not add custom Installation.', Logger::L_INFO ); return; } if ( $this->custWpInstalls == null ) { $this->custWpInstalls = array(); } $count = count($wpInstallsInfo); for ( $i = 0; $i < $count; $i++ ) { $infoString = $wpInstallsInfo[$i]; $info = preg_split('/\s+/', trim($infoString)); $line = $i + 1; if ( count($info) != 4 ) { $this->log( 'Incorrect number of values for custom installation input ' . "string on line $line. Skipping.", Logger::L_INFO ); continue; } $wpPath = $info[0]; $docroot = $info[1]; $serverName = $info[2]; $siteUrl = $info[3]; if ( !file_exists("$wpPath/wp-admin") ) { $this->log( "No 'wp-admin' directory found for $wpPath on line " . "$line. Skipping.", Logger::L_INFO ); continue; } if ( !(substr($wpPath, 0, strlen($docroot)) === $docroot) ) { $this->log( "docroot not contained in $wpPath on line $line. " . 'Skipping.', Logger::L_INFO ); continue; } if ( !isset($this->wpInstalls[$wpPath]) ) { $this->custWpInstalls[$wpPath] = new WPInstall($wpPath); $this->custWpInstalls[$wpPath]->setDocRoot($docroot); $this->custWpInstalls[$wpPath]->setServerName($serverName); $this->custWpInstalls[$wpPath]->setSiteUrlDirect($siteUrl); $this->custWpInstalls[$wpPath]->refreshStatus(); $this->log( "New installation added to custom data file: $wpPath", Logger::L_INFO ); } else { $this->log( "Installation already found during scan: $wpPath. " . 'Skipping.', Logger::L_INFO ); } } } /** * Get all WPInstall command messages as a key=>value array. * * @return string[][] */ public function getAllCmdMsgs() { $succ = $fail = $err = array(); foreach ( $this->workingQueue as $WPInstall ) { $cmdStatus = $WPInstall->getCmdStatus(); if ( $cmdStatus & UserCommand::EXIT_SUCC ) { $msgType = &$succ; } elseif ( $cmdStatus & UserCommand::EXIT_FAIL ) { $msgType = &$fail; } elseif ( $cmdStatus & UserCommand::EXIT_ERROR ) { $msgType = &$err; } else { continue; } if ( $msg = $WPInstall->getCmdMsg() ) { $msgType[] = "{$WPInstall->getPath()} - $msg"; } } return array( 'succ' => $succ, 'fail' => $fail, 'err' => $err ); } /** * * @param string $msg * @param int $level * @throws LSCMException Thrown indirectly. */ protected function log( $msg, $level ) { $msg = "WPInstallStorage - {$msg}"; switch ($level) { case Logger::L_ERROR: Logger::error($msg); break; case Logger::L_WARN: Logger::warn($msg); break; case Logger::L_NOTICE: Logger::notice($msg); break; case Logger::L_INFO: Logger::info($msg); break; case Logger::L_VERBOSE: Logger::verbose($msg); break; case Logger::L_DEBUG: Logger::debug($msg); break; //no default } } }
| ver. 1.4 |
Github
|
.
| PHP 8.2.28 | Generation time: 0.03 |
proxy
|
phpinfo
|
Settings