Current Path : /var/www/mainsite/wp-content/plugins/duplicator-pro/src/Libs/Chunking/ |
Current File : /var/www/mainsite/wp-content/plugins/duplicator-pro/src/Libs/Chunking/ChunkingManager.php |
<?php /** * @package Duplicator * @copyright (c) 2022, Snap Creek LLC */ namespace Duplicator\Libs\Chunking; use Duplicator\Libs\Chunking\Iterators\GenericSeekableIteratorInterface; use Duplicator\Libs\Chunking\Persistance\NoPersistanceAdapter; use Duplicator\Libs\Chunking\Persistance\PersistanceAdapterInterface; use Error; use Exception; /** * Abstract class to splita generci action with iterator */ abstract class ChunkingManager { const CHUNK_ERROR = -1; const CHUNK_COMPLETE = 0; const CHUNK_STOP = 1; /** @var GenericSeekableIteratorInterface */ protected $it = null; /** @var PersistanceAdapterInterface */ protected $persistance = 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 execution */ public $timeOut = 0; /** @var integer sleep in milliseconds every iteration */ public $throttling = 0; /** @var float */ protected $startTime = 0; /** @var integer */ protected $itCount = 0; /** @var string */ protected $lastErrorMessage = ''; /** * Class contructor * * @param mixed $extraData extra data for manager used on extended classes * @param int $maxIteration max number of iterations * @param int $timeOut timeout in milliseconds * @param int $throttling throttling lin milliseconds */ public function __construct($extraData = null, $maxIteration = 0, $timeOut = 0, $throttling = 0) { $this->maxIteration = $maxIteration; $this->timeOut = $timeOut; $this->throttling = $throttling; $this->it = $this->getIterator($extraData); $this->persistance = $this->getPersistance($extraData); if (!is_subclass_of($this->it, GenericSeekableIteratorInterface::class)) { throw new Exception('Iterator don\'t extend ' . GenericSeekableIteratorInterface::class); } } /** * Exec action on current position * * @param mixed $key Current iterator key * @param mixed $current Current iterator position * * @return bool return true on success, false on failure */ abstract protected function action($key, $current); /** * Return iterator * * @param mixed $extraData extra data for manager used on extended classes * * @return GenericSeekableIteratorInterface */ abstract protected function getIterator($extraData = null); /** * Return persistance adapter * * @param mixed $extraData extra data for manager used on extended classes * * @return PersistanceAdapterInterface */ protected function getPersistance($extraData = null) { return new NoPersistanceAdapter(); } /** * Start iterations * * @param boolean $rewind if set to true will rewind * * @return int Enum Chunk result CHUNK_ERROR,CHUNK_STOP,CHUNK_COMPLETE */ public function start($rewind = false) { $this->itCount = 0; $microThrottling = $this->throttling * 1000; if ($rewind) { $this->persistance->deletePersistanceData(); $this->it->rewind(); } elseif (($last_position = $this->persistance->getPersistanceData()) !== null) { $this->persistance->deletePersistanceData(); $this->it->gSeek($last_position); $this->it->next(); } $this->startTime(); for (; $this->it->valid(); $this->it->next()) { $this->itCount ++; $actionResult = false; try { // Execute action for current item if (($actionResult = $this->action($this->it->key(), $this->it->current())) == false) { throw new Exception('Chunk action fail'); } } catch (Exception $e) { $this->lastErrorMessage = $e->getMessage() . '[' . $e->getFile() . '|' . $e->getLine() . ']'; $actionResult = false; } catch (Error $e) { $this->lastErrorMessage = $e->getMessage() . '[' . $e->getFile() . '|' . $e->getLine() . ']'; $actionResult = false; } if ($actionResult == false) { $this->stop(); return self::CHUNK_ERROR; } if ($microThrottling) { usleep($microThrottling); } if ($this->maxIteration && $this->itCount >= $this->maxIteration || $this->checkTime() == false) { $this->stop(); return self::CHUNK_STOP; } } return self::CHUNK_COMPLETE; } /** * @param bool $saveData if set to false will not save the state * * @return mixed return position on success of false on failure */ public function stop($saveData = true) { if ($saveData) { if (!$this->persistance->savePersistanceData($this->it->getPosition(), $this->it)) { return false; } } $position = $this->it->getPosition(); $this->it->stopIteration(); return $position; } /** * Save data for persistance of chunk if persistance isn't null * * @return bool This function returns true on success, or FALSE on failure. */ protected function saveData() { return $this->persistance->savePersistanceData($this->it->getPosition(), $this->it); } /** * * @return mixed */ public function getLastPosition() { return $this->it->getPosition(); } /** * * @return int */ public function getIterationsCount() { return $this->itCount; } /** * @return void */ protected function startTime() { $this->startTime = microtime(true); } /** * Returns false if timeout > time spend * * @return boolean */ protected function checkTime() { if ($this->timeOut) { $delta = $this->getExecutionTime() * 1000; if ($delta > $this->timeOut) { return false; } } return true; } /** * * @return float */ public function getExecutionTime() { return microtime(true) - $this->startTime; } /** * Return progress percentage * * @return float progress percentage or -1 undefined */ public function getProgressPerc() { return $this->it->getProgressPerc(); } /** * Get last error message, empty if no error * * @return string */ public function getLastErrorMessage() { return $this->lastErrorMessage; } }