forked from kaliop-uk/ezmigrationbundle
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
gggeek
committed
May 4, 2018
1 parent
001b4a8
commit e1fc17c
Showing
5 changed files
with
199 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<?php | ||
|
||
namespace Kaliop\eZMigrationBundle\Core\Executor; | ||
|
||
use Kaliop\eZMigrationBundle\API\Value\MigrationStep; | ||
use Kaliop\eZMigrationBundle\Core\MigrationService; | ||
use Kaliop\eZMigrationBundle\Core\ReferenceResolver\LoopResolver; | ||
|
||
class LoopExecutor extends AbstractExecutor | ||
{ | ||
use IgnorableStepExecutorTrait; | ||
|
||
protected $supportedStepTypes = array('loop'); | ||
|
||
/** @var MigrationService $migrationService */ | ||
protected $migrationService; | ||
|
||
/** @var LoopResolver $loopResolver */ | ||
protected $loopResolver; | ||
|
||
public function __construct($migrationService, $loopResolver) | ||
{ | ||
$this->migrationService = $migrationService; | ||
$this->loopResolver = $loopResolver; | ||
} | ||
|
||
/** | ||
* @param MigrationStep $step | ||
* @return mixed | ||
* @throws \Exception | ||
*/ | ||
public function execute(MigrationStep $step) | ||
{ | ||
parent::execute($step); | ||
|
||
if (!isset($step->dsl['repeat']) || $step->dsl['repeat'] < 0) { | ||
throw new \Exception("Invalid step definition: missing 'repeat' or not a positive integer"); | ||
} | ||
|
||
if (!isset($step->dsl['steps']) || !is_array($step->dsl['steps'])) { | ||
throw new \Exception("Invalid step definition: missing 'steps' or not an array"); | ||
} | ||
|
||
// no need for a 'mode' for now | ||
/*$action = $step->dsl['mode']; | ||
if (!in_array($action, $this->supportedActions)) { | ||
throw new \Exception("Invalid step definition: value '$action' is not allowed for 'mode'"); | ||
}*/ | ||
|
||
$this->skipStepIfNeeded($step); | ||
|
||
// before engaging in the loop, check that all steps are valid | ||
$stepExecutors = array(); | ||
foreach ($step->dsl['steps'] as $i => $stepDef) { | ||
$type = $stepDef['type']; | ||
try { | ||
$stepExecutors[$i] = $this->migrationService->getExecutor($type); | ||
} catch (\InvalidArgumentException $e) { | ||
throw new \InvalidArgumentException($e->getMessage() . " in sub-step of a loop step"); | ||
} | ||
} | ||
|
||
$this->loopResolver->beginLoop(); | ||
$result = null; | ||
|
||
// NB: we are *not* firing events for each pass of the loop... it might be worth making that optionally happen ? | ||
for ($i = 0; $i < $step->dsl['repeat']; $i++) { | ||
|
||
$this->loopResolver->loopStep(); | ||
|
||
foreach ($step->dsl['steps'] as $j => $stepDef) { | ||
$type = $stepDef['type']; | ||
unset($stepDef['type']); | ||
$subStep = new MigrationStep($type, $stepDef, array_merge($step->context, array())); | ||
$result = $stepExecutors[$j]->execute($subStep); | ||
} | ||
} | ||
|
||
$this->loopResolver->endLoop(); | ||
return $result; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<?php | ||
|
||
namespace Kaliop\eZMigrationBundle\Core\ReferenceResolver; | ||
|
||
class LoopResolver extends AbstractResolver | ||
{ | ||
protected $referencePrefixes = array('loop:'); | ||
|
||
protected $stack = array(); | ||
|
||
public function beginLoop() | ||
{ | ||
$this->stack[] = 0; | ||
} | ||
|
||
public function endLoop() | ||
{ | ||
array_pop($this->stack); | ||
} | ||
|
||
public function loopStep() | ||
{ | ||
$idx = count($this->stack) - 1; | ||
$this->stack[$idx] = $this->stack[$idx] + 1; | ||
} | ||
|
||
/** | ||
* @param string $identifier format: 'loop:index', 'loop:depth' | ||
* @return int | ||
* @throws \Exception When trying to retrieve anything else but index and depth | ||
*/ | ||
public function getReferenceValue($identifier) | ||
{ | ||
switch(substr($identifier, 5)) { | ||
case 'iteration': | ||
return end($this->stack); | ||
case 'depth': | ||
return count($this->stack); | ||
default: | ||
throw new \Exception("Can not resolve loop value '$identifier'"); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# Loop steps allow to execute maultiple times in a row (a sequence of) other steps. | ||
# Nested loops are supported. | ||
# NB: step execution events are triggered only for the outhermost loop step | ||
|
||
- | ||
type: loop | ||
repeat: int # number of times to repeat execution of the sequence of sub-steps | ||
steps: # the migration steps that you want to be executed repeatedly | ||
- | ||
type: ... | ||
mode: ... | ||
etc: ... # New references that can be resolved anywhere inside the nested step definitions are `loop:index` | ||
# and `loop:depth`. | ||
# loop:iteration is the counter of the current loop iteration, starting at 1 | ||
# loop:depth is used to tell apart nested loops. I starts at depth 1 | ||
# f.e. you could use the following to create contents with different names: "Article [loop:depth].[loop:iteration]" | ||
- | ||
type: ... | ||
mode: ... | ||
etc: ... | ||
|
||
if: # Optional. If set, the loop will be skipped unless the condition is matched | ||
"reference:_ref_name": # name of a reference to be used for the test | ||
_operator_: value # allowed operators: eq, gt, gte, lt, lte, ne, count, length, regexp | ||
|
||
# Example: how to create a reference that holds a composite index of the current step in nested loops: | ||
|
||
- | ||
type: loop | ||
repeat: 2 | ||
steps: | ||
- | ||
type: reference | ||
mode: set | ||
identifier: loopindex1 | ||
value: "[loop:iteration]" | ||
overwrite: true | ||
- | ||
type: loop | ||
repeat: 2 | ||
steps: | ||
- | ||
type: reference | ||
mode: set | ||
identifier: loopindex2 | ||
value: "[reference:loopindex1].[loop:iteration]" | ||
overwrite: true | ||
- | ||
type: reference | ||
mode: dump | ||
identifier: reference:loopindex2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters