Seditio Source
Root |
./othercms/xenForo 2.2.8/src/XF/AddOn/StepRunnerUpgradeTrait.php
<?php

namespace XF\AddOn;

use function
intval, is_array;

/**
 * @property AddOn $addOn
 */
trait StepRunnerUpgradeTrait
{
   
/**
     * @param array $stepParams
     *
     * @return null|StepResult
     */
   
public function upgrade(array $stepParams = [])
    {
       
$stepParams = $this->getStepParams($stepParams);

       
$versions = [];
       
$stepsGrouped = [];

       
$reflection = new \ReflectionObject($this);
        foreach (
$reflection->getMethods() AS $method)
        {
            if (
preg_match('/^upgrade(\d+)Step(\d+)$/', $method->name, $match))
            {
               
$versionId = intval($match[1]);
               
$step = intval($match[2]);

               
$versions[] = $versionId;
               
$stepsGrouped[$versionId][$step] = $step;
            }
        }

        if (!
$versions)
        {
            return
null;
        }

        if (!
$stepParams['version_id'])
        {
           
$resume = $this->getUpgradeResumeStep();
           
$stepParams['version_id'] = $resume[0];
           
$stepParams['step'] = $resume[1];
        }

       
$runStep = $stepParams['step'];
        if (!
$runStep)
        {
           
$runStep = 1;
        }

       
$versions = array_unique($versions);
       
sort($versions, SORT_NUMERIC);

        foreach (
$versions AS $i => $versionId)
        {
            if (
$versionId >= $stepParams['version_id'])
            {
               
$versionSteps = $stepsGrouped[$versionId];
                if (isset(
$versionSteps[$runStep]))
                {
                    if (
$versionId != $stepParams['version_id'] || $runStep != $stepParams['step'])
                    {
                       
// sanity check - don't pass params if we're changing versions or steps
                       
$stepParams = [];
                    }

                   
$nextVersionId = $versions[$i + 1] ?? null;

                    return
$this->upgradeStepRunner($versionId, $runStep, $stepParams, $nextVersionId);
                }

               
// if we hit here, then the step couldn't be found, so move onto the next upgrade
               
$runStep = 1;
               
$stepParams = $this->getStepParams();
            }
        }

       
// if we got here, we don't have any other upgrades to run
       
return null;
    }

    protected function
getStepParams(array $stepParams = [])
    {
        return
array_replace([
           
'version_id' => 0,
           
'step' => 0
       
], $stepParams);
    }

    private function
getUpgradeResumeStep()
    {
       
$installedAddOn = $this->addOn->getInstalledAddOn();
       
$lastActionStep = $installedAddOn->getLastActionStep('upgrade');
        if (
$lastActionStep)
        {
           
$lastActionStep[1]++; // we completed this step, so need to resume with the next
           
return $lastActionStep;
        }

        return [
$this->addOn->getInstalledAddOn()->version_id + 1, 1];
    }

   
/**
     * @param integer $runVersion
     * @param integer $runStep
     * @param array $stepParams
     * @param integer|null $nextVersionId
     *
     * @return null|StepResult
     */
   
private function upgradeStepRunner($runVersion, $runStep, array $stepParams, $nextVersionId)
    {
       
$fnPattern = 'upgrade%dStep%d';
       
$fn = sprintf($fnPattern, $runVersion, $runStep);
        if (!
method_exists($this, $fn))
        {
            throw new \
LogicException("Step $fn doesn't exist. Should have been checked earlier.");
        }

       
$result = $this->$fn($stepParams);
        if (
$result === null || $result === true)
        {
           
$result = new StepResult(true);
        }
        else if (
is_array($result))
        {
           
$result = new StepResult(false, $result);
        }

        if (!(
$result instanceof StepResult))
        {
            throw new \
LogicException("Must return a StepResult object");
        }

       
$result->step = $runStep;
       
$result->version = $runVersion;

        if (
$result->complete)
        {
           
$this->addOn->updatePendingAction('upgrade', $result->version . ':' . $result->step);

           
$nextStep = $runStep + 1;
           
$nextStepFn = sprintf($fnPattern, $runVersion, $nextStep);
            if (
method_exists($this, $nextStepFn))
            {
               
$result = new StepResult(false, [], $nextStep, $runVersion);
            }
            else
            {
               
// we're done this upgrade version, see if we have another
               
if ($nextVersionId === null)
                {
                    return
null;
                }

               
$nextFn = sprintf($fnPattern, $nextVersionId, 1);
                if (!
method_exists($this, $nextFn))
                {
                    return
null;
                }

               
$result = new StepResult(false, [], 1, $nextVersionId);
            }
        }

        return
$result;
    }
}