View file upload/src/addons/AddonsLab/Core/StepRunner/StepRunner.php

File size: 4.6Kb
<?php
/** 
This software is furnished under a license and may be used and copied
only  in  accordance  with  the  terms  of such  license and with the
inclusion of the above copyright notice.  This software  or any other
copies thereof may not be provided or otherwise made available to any
other person.  No title to and  ownership of the  software is  hereby
transferred.                                                         
                                                                     
You may not reverse  engineer, decompile, defeat  license  encryption
mechanisms, or  disassemble this software product or software product
license.  AddonsLab may terminate this license if you don't comply with
any of these terms and conditions.  In such event,  licensee  agrees 
to return licensor  or destroy  all copies of software  upon termination 
of the license.
*/


namespace AddonsLab\Core\StepRunner;

/**
 * Class StepRunner
 * @package AddonsLab\Core\StepRunner
 * Abstracts any scenario tasks should run multiple times (e.g. by reloading the page)
 */
class StepRunner
{
    protected $runState;

    /**
     * @var StepInterface[]
     */
    protected $steps = array();

    /**
     * @var \Closure
     * Will run before the first step
     */
    protected $install_callback;
    /**
     * @var \Closure
     * Will run after the last step
     */
    protected $uninstall_callback;

    public function __construct(RunState $runState)
    {
        $this->runState = $runState;
    }

    public function addStep(StepInterface $step)
    {
        $this->steps[$step->getId()] = $step;
    }

    /**
     * @param StepInterface[] $steps
     */
    public function addSteps(array $steps)
    {
        foreach ($steps AS $step) {
            $this->addStep($step);
        }
    }

    /**
     * @return RunState|true
     * If true is returned, the caller can assume all steps are processed
     * Otherwise RunState is returned
     */
    public function run()
    {
        // nothing to run
        if (empty($this->steps)) {
            return true;
        }

        $stepId = &$this->runState->step_id;

        // a predefined step name to stop the loop
        if ($stepId === 'done') {
            return true;
        }

        if ($stepId === false) {
            // no step run yet
            $stepId = $this->_getFirstStepId();
            if ($this->install_callback !== null) {
                $this->install_callback->call($this);
            }
        }

        $step = $this->steps[$stepId];

        if ($this->runState->total === false) {
            $this->runState->total = intval($step->getTotal());
        }

        if ($this->runState->total === 0) {
            // not items to import, step is done anyway
            return true;
        }

        $result = $step->run($this->runState);

        if ($result === true) {
            // the step completed, check for the next step
            $nextStepId = $this->_getNextStepId($stepId);
            if ($nextStepId === false) {
                // all steps are done, return true to indicate all tasks are done
                if ($this->uninstall_callback !== null) {
                    $this->uninstall_callback->call($this);
                }

                $nextStepId = 'done';
                $total=0;
            } else {
                $nextStep=$this->steps[$nextStepId];
                $total=$nextStep->getTotal();
            }

            $runStatus = $this->runState;
            $runStatus->step_id = $nextStepId;
            $runStatus->index = 0;
            $runStatus->total = $total;
            return $runStatus;
        }

        // the step should still run
        return $result;
    }

    public function getStepId($stepId)
    {
        return $this->steps[$stepId]->getId();
    }

    /**
     * @param $stepId
     * @return string|false
     * String if the next step is defined, false if no next step
     */
    public function _getNextStepId($stepId)
    {
        $stepIds = array_keys($this->steps);

        $stepIndex = array_search($stepId, $stepIds, true);

        if ($stepIndex === count($stepIds)-1) {
            // this was the last step, no next step
            return false;
        }

        return $stepIds[$stepIndex + 1];
    }

    protected function _getFirstStepId()
    {
        $array = array_keys($this->steps);
        
        return $array[0];
    }

    public function setInstallCallback(\Closure $install_callback)
    {
        $this->install_callback = $install_callback;
    }

    public function setUninstallCallback(\Closure $uninstall_callback)
    {
        $this->uninstall_callback = $uninstall_callback;
    }
}