Changed source root directory

This commit is contained in:
2026-03-05 16:30:11 +01:00
parent dc85447ee1
commit 538f85d7a2
5868 changed files with 749734 additions and 99 deletions

View File

@@ -0,0 +1,34 @@
<?php
/**
* Standard: PSR-2
*
* @link http://www.php-fig.org/psr/psr-2 Full Documentation
*
* @package SC\DUPX\Chunk
*/
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
/**
* Event iterator
*/
interface EventIterator extends Iterator
{
/**
* The callback accept 3 params
* $event , $index and $current values
*
* @param null | callable $callback
*/
public function setEventCallback($callback = null);
/**
* Execute event
*
* @param mixed $event
* @param mixed $key
* @param mixed $current
*/
public function doEvent($event, $key, $current);
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* Standard: PSR-2
*
* @link http://www.php-fig.org/psr/psr-2 Full Documentation
*
* @package SC\DUPX\Chunk
*/
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
/**
*
* @author andrea
*/
interface GenericSeekableIterator extends Iterator
{
/**
*
* @param mixed $position
*
* @return bool
*/
public function gSeek($position);
/**
* return current position
*
* @return mixed
*/
public function getPosition();
/**
* Free resources in current iteration
*/
public function stopIteration();
/**
* Return iterations count
*/
public function itCount();
}

View File

@@ -0,0 +1,248 @@
<?php
/**
* Step 3 iterator
*
* Standard: PSR-2
*
* @link http://www.php-fig.org/psr/psr-2 Full Documentation
*
* @package SC\DUPX\Chunk
*/
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
use Duplicator\Installer\Utils\Log\Log;
require_once(DUPX_INIT . '/classes/chunk/Iterators/Interfaces/GenericSeekableIterator.php');
/**
* Description of class
*
* @author andrea
*/
class DUPX_s3_iterator implements GenericSeekableIterator
{
const STEP_START = 'start';
const STEP_CLEANUP_EXTREA = 'cleanup_extra';
const STEP_CLEANUP_PACKAGES = 'cleanup_packages';
const STEP_CLEANUP_OPTIONS = 'cleanup_trans';
const STEP_SEARCH_AND_REPLACE_INIT = 'init';
const STEP_SEARCH_AND_REPLACE = 'search_replace';
const STEP_REMOVE_MAINTENACE = 'rem_maintenance';
const STEP_CREATE_ADMIN = 'create_admin';
const STEP_CONF_UPDATE = 'config_update';
const STEP_GEN_UPD = 'gen_update';
const STEP_GEN_CLEAN = 'gen_clean';
const STEP_NOTICE_TEST = 'notice_test';
const STEP_CLEANUP_TMP_FILES = 'cleanup_tmp_files';
const STEP_SET_FILE_PERMS = 'set_files_perms';
const STEP_FINAL_REPORT_NOTICES = 'final_report';
private static $numIterations = 10;
protected $position = array(
'l0' => self::STEP_SEARCH_AND_REPLACE_INIT,
'l1' => null,
'l2' => null
);
protected $isValid = true;
protected $tablesIterator = null;
public function __construct()
{
$tables = DUPX_DB_Tables::getInstance()->getReplaceTablesNames();
$this->tablesIterator = new ArrayIterator($tables);
$this->rewind();
}
#[\ReturnTypeWillChange]
public function rewind()
{
$this->isValid = true;
$this->position = array(
'l0' => self::STEP_START,
'l1' => null,
'l2' => null
);
$this->tablesIterator->rewind();
}
#[\ReturnTypeWillChange]
public function next()
{
switch ($this->position['l0']) {
case self::STEP_START:
$this->position['l0'] = self::STEP_CLEANUP_OPTIONS;
break;
case self::STEP_CLEANUP_OPTIONS:
$this->position['l0'] = self::STEP_CLEANUP_EXTREA;
break;
case self::STEP_CLEANUP_EXTREA:
$this->position['l0'] = self::STEP_CLEANUP_PACKAGES;
break;
case self::STEP_CLEANUP_PACKAGES:
$this->position['l0'] = self::STEP_SEARCH_AND_REPLACE_INIT;
break;
case self::STEP_SEARCH_AND_REPLACE_INIT:
if ($this->getNextSearchReplacePosition(true)) {
// if search and replace is valid go to STEP_SEARCH_AND_REPLACE
$this->position['l0'] = self::STEP_SEARCH_AND_REPLACE;
} else {
// if search and replace isn't valid skip STEP_SEARCH_AND_REPLACE and go to STEP_REMOVE_MAINTENACE
$this->position['l0'] = self::STEP_REMOVE_MAINTENACE;
}
break;
case self::STEP_SEARCH_AND_REPLACE:
if (!$this->getNextSearchReplacePosition()) {
$this->position['l0'] = self::STEP_REMOVE_MAINTENACE;
}
break;
case self::STEP_REMOVE_MAINTENACE:
$this->position['l0'] = self::STEP_CONF_UPDATE;
break;
case self::STEP_CONF_UPDATE:
$this->position['l0'] = self::STEP_GEN_UPD;
break;
case self::STEP_GEN_UPD:
$this->position['l0'] = self::STEP_GEN_CLEAN;
break;
case self::STEP_GEN_CLEAN:
$this->position['l0'] = self::STEP_CREATE_ADMIN;
break;
case self::STEP_CREATE_ADMIN:
$this->position['l0'] = self::STEP_NOTICE_TEST;
break;
case self::STEP_NOTICE_TEST:
$this->position['l0'] = self::STEP_CLEANUP_TMP_FILES;
break;
case self::STEP_CLEANUP_TMP_FILES:
$this->position['l0'] = self::STEP_SET_FILE_PERMS;
break;
case self::STEP_SET_FILE_PERMS:
$this->position['l0'] = self::STEP_FINAL_REPORT_NOTICES;
break;
case self::STEP_FINAL_REPORT_NOTICES:
default:
$this->position['l0'] = null;
$this->isValid = false;
}
}
private function getNextSearchReplacePosition($init = false)
{
$valid = true;
$s3func = DUPX_S3_Funcs::getInstance();
$pages = isset($s3func->cTableParams['pages']) ? $s3func->cTableParams['pages'] : 0;
$this->position['l2'] = (int) $this->position['l2'];
$this->position['l2']++;
if ($this->position['l2'] < $pages) {
/* NEXT PAGE */
Log::info('ITERATOR INCREMENT PAGE: ' . $this->position['l2'] . ' PAGES[' . $pages . ']', 3);
$s3func->cTableParams['page'] = $this->position['l2'];
} else {
if ($init) {
DUPX_UpdateEngine::loadInit();
Log::info('ITERATOR FIRST TABLE: ' . $this->position['l2'] . ' PAGES[' . $pages . ']', 3);
$this->tablesIterator->rewind();
} else {
Log::info('ITERATOR INCREMENT TABLE: ' . $this->position['l2'] . ' PAGES[' . $pages . ']', 3);
if ($s3func->cTableParams['updated']) {
$s3func->report['updt_tables']++;
}
$this->tablesIterator->next();
}
$this->position['l1'] = $this->tablesIterator->key();
$this->position['l2'] = 0;
// search first table with rows and columns
while ($this->tablesIterator->valid()) {
Log::info('ITERATOR CHECK TABLE: ' . $this->tablesIterator->current(), 3);
// init table params if isn't initialized
if (DUPX_UpdateEngine::initTableParams($this->tablesIterator->current())) {
// table with columns and rows found
break;
}
// NEXT TABLE
$this->tablesIterator->next();
}
if ($this->tablesIterator->valid()) {
$this->position['l1'] = $this->tablesIterator->key();
$this->position['l2'] = 0;
} else {
$this->position['l1'] = null;
$this->position['l2'] = null;
$s3func->cTableParams = null;
DUPX_UpdateEngine::loadEnd();
DUPX_UpdateEngine::logStats();
DUPX_UpdateEngine::logErrors();
$valid = false;
}
}
return $valid;
}
public function gSeek($position)
{
$this->position = $position;
switch ($this->position['l0']) {
case self::STEP_SEARCH_AND_REPLACE:
$this->tablesIterator->seek($this->position['l1']);
break;
default:
}
}
public function getPosition()
{
return $this->position;
}
#[\ReturnTypeWillChange]
public function key()
{
return implode('_', $this->position);
}
#[\ReturnTypeWillChange]
public function current()
{
$result = array(
'l0' => $this->position['l0'],
'l1' => null,
'l2' => null
);
$result['l0'] = $this->position['l0'];
switch ($this->position['l0']) {
case self::STEP_SEARCH_AND_REPLACE:
$result['l1'] = $this->tablesIterator->current();
$result['l2'] = $this->position['l2'];
break;
default:
}
return $result;
}
public function stopIteration()
{
switch ($this->position['l0']) {
case self::STEP_SEARCH_AND_REPLACE:
DUPX_UpdateEngine::commitAndSave();
break;
default:
}
}
#[\ReturnTypeWillChange]
public function valid()
{
return $this->isValid;
}
public function itCount()
{
return self::$numIterations;
}
}

View File

@@ -0,0 +1,230 @@
<?php
/**
* Chunk manager step 3
*
* Standard: PSR-2
*
* @link http://www.php-fig.org/psr/psr-2 Full Documentation
*
* @package SC\DUPX\Chunk
*/
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
use Duplicator\Installer\Core\Deploy\Database\DbCleanup;
use Duplicator\Installer\Utils\Log\Log;
use Duplicator\Installer\Utils\Log\LogHandler;
use Duplicator\Libs\Snap\SnapJson;
require_once(DUPX_INIT . '/classes/chunk/class.chunkingmanager_file.php');
require_once(DUPX_INIT . '/classes/chunk/Iterators/class.s3.iterator.php');
/**
* Chunk manager step 3
*
* @author andrea
*/
class DUPX_chunkS3Manager extends DUPX_ChunkingManager_file
{
/**
* Exectute action for every iteration
*
* @param string $key
* @param array $current
*/
protected function action($key, $current)
{
$s3FuncsManager = DUPX_S3_Funcs::getInstance();
Log::info('CHUNK ACTION: CURRENT [' . implode('][', $current) . ']');
switch ($current['l0']) {
case DUPX_s3_iterator::STEP_START:
$s3FuncsManager->initLog();
$s3FuncsManager->initChunkLog($this->maxIteration, $this->timeOut, $this->throttling, $GLOBALS['DATABASE_PAGE_SIZE']);
break;
case DUPX_s3_iterator::STEP_CLEANUP_OPTIONS:
DbCleanup::cleanupOptions();
break;
case DUPX_s3_iterator::STEP_CLEANUP_EXTREA:
DbCleanup::cleanupExtra();
break;
case DUPX_s3_iterator::STEP_CLEANUP_PACKAGES:
DbCleanup::cleanupPackages();
break;
case DUPX_s3_iterator::STEP_SEARCH_AND_REPLACE_INIT:
break;
case DUPX_s3_iterator::STEP_SEARCH_AND_REPLACE:
DUPX_UpdateEngine::evaluateTableRows($current['l1'], $current['l2']);
DUPX_UpdateEngine::commitAndSave();
break;
case DUPX_s3_iterator::STEP_REMOVE_MAINTENACE:
$s3FuncsManager->removeMaintenanceMode();
break;
case DUPX_s3_iterator::STEP_CREATE_ADMIN:
$s3FuncsManager->createNewAdminUser();
break;
case DUPX_s3_iterator::STEP_CONF_UPDATE:
$s3FuncsManager->configFilesUpdate();
break;
case DUPX_s3_iterator::STEP_GEN_UPD:
$s3FuncsManager->generalUpdate();
break;
case DUPX_s3_iterator::STEP_GEN_CLEAN:
$s3FuncsManager->generalCleanup();
$s3FuncsManager->forceLogoutOfAllUsers();
$s3FuncsManager->duplicatorMigrationInfoSet();
break;
case DUPX_s3_iterator::STEP_NOTICE_TEST:
$s3FuncsManager->checkForIndexHtml();
$s3FuncsManager->noticeTest();
break;
case DUPX_s3_iterator::STEP_CLEANUP_TMP_FILES:
$s3FuncsManager->cleanupTmpFiles();
break;
case DUPX_s3_iterator::STEP_SET_FILE_PERMS:
$s3FuncsManager->setFilePermsission();
break;
case DUPX_s3_iterator::STEP_FINAL_REPORT_NOTICES:
$s3FuncsManager->finalReportNotices();
break;
default:
}
/**
* At each iteration save the status in case of exit with timeout
*/
$this->saveData();
}
protected function getIterator()
{
return new DUPX_s3_iterator();
}
public function getStoredDataKey()
{
return $GLOBALS["CHUNK_DATA_FILE_PATH"];
}
/**
* stop iteration without save data.
* It is already saved every iteration.
*
* @return mixed
*/
public function stop($saveData = false)
{
return parent::stop(false);
}
/**
* load data from previous step if exists adn restore _POST and GLOBALS
*
* @param string $key file name
*
* @return mixed
*/
protected function getStoredData($key)
{
if (($data = parent::getStoredData($key)) != null) {
Log::info("CHUNK LOAD DATA: POSITION " . implode(' / ', $data['position']), 2);
return $data['position'];
} else {
Log::info("CHUNK LOAD DATA: IS NULL ");
return null;
}
}
/**
* delete stored data if exists
*/
protected function deleteStoredData($key)
{
Log::info("CHUNK DELETE STORED DATA FILE:" . Log::v2str($key), 2);
return parent::deleteStoredData($key);
}
/**
* save data for next step
*/
protected function saveStoredData($key, $data)
{
// store s3 func data
$s3Funcs = DUPX_S3_Funcs::getInstance();
$s3Funcs->report['chunk'] = 1;
$s3Funcs->report['chunkPos'] = $data;
$s3Funcs->report['pass'] = 0;
$s3Funcs->report['progress_perc'] = $this->getProgressPerc();
$s3Funcs->saveData();
// managed output for timeout shutdown
LogHandler::setShutdownReturn(LogHandler::SHUTDOWN_TIMEOUT, SnapJson::jsonEncode($s3Funcs->getJsonReport()));
/**
* store position post and globals
*/
$gData = array(
'position' => $data
);
Log::info("CHUNK SAVE DATA: POSITION " . implode(' / ', $data), 2);
return parent::saveStoredData($key, $gData);
}
/**
*
* @return float progress in %
*/
public function getProgressPerc()
{
$result = 0;
$position = $this->it->getPosition();
$s3Func = DUPX_S3_Funcs::getInstance();
switch ($position['l0']) {
case DUPX_s3_iterator::STEP_SEARCH_AND_REPLACE_INIT:
$result = 5;
break;
case DUPX_s3_iterator::STEP_SEARCH_AND_REPLACE:
$lowLimit = 10;
$higthLimit = 90;
$stepDelta = $higthLimit - $lowLimit;
$tables = DUPX_DB_Tables::getInstance()->getReplaceTablesNames();
$tableDelta = $stepDelta / (count($tables) + 1);
$singePagePerc = $tableDelta / ($s3Func->cTableParams['pages'] + 1);
$result = round($lowLimit + ($tableDelta * (int) $position['l1']) + ($singePagePerc * (int) $position['l2']), 2);
break;
case DUPX_s3_iterator::STEP_REMOVE_MAINTENACE:
$result = 90;
break;
case DUPX_s3_iterator::STEP_CREATE_ADMIN:
$result = 92;
break;
case DUPX_s3_iterator::STEP_CONF_UPDATE:
$result = 93;
break;
case DUPX_s3_iterator::STEP_GEN_UPD:
$result = 94;
break;
case DUPX_s3_iterator::STEP_GEN_CLEAN:
$result = 95;
break;
case DUPX_s3_iterator::STEP_NOTICE_TEST:
$result = 96;
break;
case DUPX_s3_iterator::STEP_CLEANUP_TMP_FILES:
$result = 97;
break;
case DUPX_s3_iterator::STEP_SET_FILE_PERMS:
$result = 98;
break;
case DUPX_s3_iterator::STEP_FINAL_REPORT_NOTICES:
$result = 100;
break;
default:
}
return $result;
}
}

View File

@@ -0,0 +1,226 @@
<?php
/**
* Cunking manager
*
* Standard: PSR-2
*
* @link http://www.php-fig.org/psr/psr-2 Full Documentation
*
* @package SC\DUPX\Chunk
*/
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
/**
* Abstract class to split an single ajax requet in multiple requests
*/
abstract class DUPX_ChunkingManager
{
/** @var GenericSeekableIterator */
protected $it = null;
/** @var mixed */
protected $position = null;
/** @var integer max iteration before stop. If 0 have no limit */
public $maxIteration = 0;
/** @var integer timeout in milliseconds before stop exectution */
public $timeOut = 0;
/** @var integer sleep in milliseconds every iteration */
public $throttling = 0;
/** @var float */
protected $startTime = null;
/** @var integer */
protected $itCount = 0;
/**
* set params
*
* @param number $maxIteration
* @param number $timeOut
* @param number $throttling
*/
public function __construct($maxIteration = 0, $timeOut = 0, $throttling = 0)
{
$this->maxIteration = $maxIteration;
$this->timeOut = $timeOut;
$this->throttling = $throttling;
$this->it = $this->getIterator();
if (!is_subclass_of($this->it, 'GenericSeekableIterator')) {
throw new Exception('Iterator don\'t extend GenericSeekableIterator');
}
}
/**
*
* @param boolean $rewind
*
* @return boolean true if execution completed false if stopped
*/
public function start($rewind = false)
{
$this->itCount = 0;
$microThrottling = $this->throttling * 1000;
if ($rewind) {
/**
* delete store data and rewind
*/
$this->deleteStoredData($this->getStoredDataKey());
$this->it->rewind();
} elseif (( $last_position = $this->getStoredData($this->getStoredDataKey()) ) !== null) {
/**
* load last position if exist and delete it
*/
$this->deleteStoredData($this->getStoredDataKey());
$this->it->gSeek($last_position);
$this->it->next();
}
$this->startTime();
/**
* Iterate
*/
for (; $this->it->valid(); $this->it->next()) {
$this->itCount++;
/**
* excetute action for current item
*/
$this->action($this->it->key(), $this->it->current());
if ($microThrottling) {
usleep($microThrottling);
}
if ($this->maxIteration && $this->itCount >= $this->maxIteration || $this->checkTime() == false) {
$this->stop();
return false;
}
}
return true;
}
/**
* var bool $saveData is fals don't save data. Used in extended classe fot don't save data on stop.
*
* @return mixed
*/
public function stop($saveData = true)
{
if ($saveData) {
if (!$this->saveStoredData($this->getStoredDataKey(), $this->it->getPosition())) {
return null;
}
}
$position = $this->it->getPosition();
$this->it->stopIteration();
return $position;
}
protected function saveData()
{
if (!$this->saveStoredData($this->getStoredDataKey(), $this->it->getPosition())) {
return null;
}
}
/**
*
* @return mixed
*/
public function getLastPosition()
{
return $this->it->getPosition();
}
/**
*
* @return number
*/
public function getIterationsCount()
{
return $this->itCount;
}
/**
* @return void
*/
protected function startTime()
{
$this->startTime = microtime(true);
}
/**
*
* @return boolean
*/
protected function checkTime()
{
if ($this->timeOut) {
$delta = $this->getExecutionTime() * 1000;
if ($delta > $this->timeOut) {
return false;
}
}
return true;
}
/**
*
* @return number
*/
public function getExecutionTime()
{
return microtime(true) - $this->startTime;
}
/**
* Get stored data key
*/
abstract public function getStoredDataKey();
/**
* load data from previous step if exists
*/
abstract protected function getStoredData($key);
/**
* delete stored data if exists
*/
abstract protected function deleteStoredData($key);
/**
* save data for next step
*/
abstract protected function saveStoredData($key, $data);
/**
*
* @param mixed $key
* @param mixed $current
*/
abstract protected function action($key, $current);
/**
* @return GenericSeekableIterator
*/
abstract protected function getIterator();
/**
* @return int
*/
abstract public function getProgressPerc();
}

View File

@@ -0,0 +1,66 @@
<?php
/**
* Cunking manager with stored data in json file.
*
* Standard: PSR-2
*
* @link http://www.php-fig.org/psr/psr-2 Full Documentation
*
* @package SC\DUPX\Chunk
*/
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
use Duplicator\Libs\Snap\SnapJson;
require_once(DUPX_INIT . '/classes/chunk/class.chunkingmanager.php');
/**
* Store position on json file
*/
abstract class DUPX_ChunkingManager_file extends DUPX_ChunkingManager
{
/**
* load data from previous step if exists
*
* @param string $key file name
*
* @return mixed
*/
protected function getStoredData($key)
{
if (file_exists($key)) {
$data = file_get_contents($key);
return json_decode($data, true);
} else {
return null;
}
}
/**
* delete stored data if exists
*/
protected function deleteStoredData($key)
{
if (file_exists($key)) {
unlink($key);
}
}
/**
*
* @param string $key file path
* @param mixed $data to save in file path
*
* @return boolean|int This function returns the number of bytes that were written to the file, or FALSE on failure.
*/
protected function saveStoredData($key, $data)
{
if (($json = SnapJson::jsonEncode($data)) === false) {
throw new Exception('Json encode chunk data error');
}
return file_put_contents($key, $json);
}
}