Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
<?php// This file is part of Moodle - https://moodle.org///// Moodle is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Moodle is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Moodle. If not, see <https://www.gnu.org/licenses/>.namespace tool_generator\local\testscenario;use behat_data_generators;use Behat\Gherkin\Node\StepNode;/*** Class to validate and process a scenario step.** @package tool_generator* @copyright 2023 Ferran Recio <ferran@moodle.com>* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/class steprunner {/** @var behat_data_generators the behat data generator instance. */private behat_data_generators $generator;/** @var array the valid steps indexed by given expression tag. */private array $validsteps;/** @var StepNode the step node to process. */private StepNode $stepnode;/** @var string|null the generator method to call. */private ?string $method = null;/** @var array the parameters to pass to the generator method. */private array $params = [];/** @var bool if the step is valid. */private bool $isvalid = false;/** @var bool if the step has been executed. */private bool $executed = false;/** @var string the error message if any. */private string $error = '';/*** Constructor.* @param behat_data_generators $generator the behat data generator instance.* @param array $validsteps the valid steps indexed by given expression tag.* @param StepNode $stepnode the step node to process.*/public function __construct(behat_data_generators $generator, array $validsteps, StepNode $stepnode) {$this->generator = $generator;$this->validsteps = $validsteps;$this->stepnode = $stepnode;$this->init();}/*** Init the step runner.** This method will check if the step is valid and all the needed information* in case it is executed.*/private function init() {$matches = [];$linetext = $this->stepnode->getText();foreach ($this->validsteps as $pattern => $method) {if (!$this->match_given($pattern, $linetext, $matches)) {continue;}$this->method = $method;$this->params = $this->build_method_params($method, $matches);$this->isvalid = true;return;}$this->error = get_string('testscenario_invalidstep', 'tool_generator');}/*** Build the method parameters.* @param string $methodname the method name.* @param array $matches the matches.* @return array the method parameters.*/private function build_method_params($methodname, $matches) {$method = new \ReflectionMethod($this->generator, $methodname);$params = [];foreach ($method->getParameters() as $param) {$paramname = $param->getName();if (isset($matches[$paramname])) {$params[] = $matches[$paramname];unset($matches[$paramname]);} else if (count($matches) > 0) {// If the param is not present means the regular expressions does not use// proper names. So we will try to find the param by position.$params[] = array_pop($matches);} else {// No more params to match.break;}}return array_merge($params, $this->stepnode->getArguments());}/*** Return if the step is valid.* @return bool*/public function is_valid(): bool {return $this->isvalid;}/*** Return if the step has been executed.* @return bool*/public function is_executed(): bool {return $this->executed;}/*** Return the step text.* @return string*/public function get_text(): string {return $this->stepnode->getText();}/*** Return the step error message.* @return string*/public function get_error(): string {return $this->error;}/*** Return the step arguments as string.* @return string*/public function get_arguments_string(): string {$result = '';foreach ($this->stepnode->getArguments() as $argument) {$result .= $argument->getTableAsString();}return $result;}/*** Match a given expression with a text.* @param string $pattern the given expression.* @param string $text the text to match.* @param array $matches the matches.* @return bool if the step matched the generator given expression.*/private function match_given(string $pattern, $text, array &$matches) {$internalmatcher = [];if (substr($pattern, 0, 1) === '/') {// Pattern is a regular expression.$result = preg_match($pattern, $text, $matches);foreach ($matches as $key => $value) {if (is_int($key)) {unset($matches[$key]);}}return $result;}// Patter is a string with parameters.$elementmatches = [];preg_match_all('/:([^ ]+)/', $pattern, $elementmatches, PREG_SET_ORDER, 0);$pattern = preg_replace('/:([^ ]+)/', '(?P<$1>"[^"]+"|[^" ]+)', $pattern);$pattern = '/^' . $pattern . '$/';$result = preg_match($pattern, $text, $internalmatcher);if (!$result) {return false;}foreach ($elementmatches as $elementmatch) {// Remove any possible " at the beggining and end of $internalmatcher[$elementmatch[1]].$paramvalue = preg_replace('/^"(.*)"$/', '$1', $internalmatcher[$elementmatch[1]]);$matches[$elementmatch[1]] = $paramvalue;}return true;}/*** Execute the step.* @return bool if the step is executed or not.*/public function execute(): bool {if (!$this->isvalid) {return false;}$this->executed = true;try {call_user_func_array([$this->generator, $this->method],$this->params);} catch (\moodle_exception $exception) {$this->error = $exception->getMessage();$this->isvalid = false;return false;}return true;}}