diff --git a/classes/helper/datafield_manager.php b/classes/helper/datafield_manager.php index 32e9de0..71fa316 100644 --- a/classes/helper/datafield_manager.php +++ b/classes/helper/datafield_manager.php @@ -162,13 +162,8 @@ public function render_datafields($templatestr, $event = null, $stepresults = nu return $value; } else { - // If there is no value, return the empty value. - if (preg_match('/\{.*?\}/', $matches[0])) { - return ''; - } else { - // No match! Leave the template string in place. - return $matches[0]; - } + // No match! Leave the template string in place. + return $matches[0]; } }; diff --git a/classes/steps/actions/webservice_action_step.php b/classes/steps/actions/webservice_action_step.php index b646ada..f937316 100644 --- a/classes/steps/actions/webservice_action_step.php +++ b/classes/steps/actions/webservice_action_step.php @@ -111,7 +111,7 @@ private function run_function() { $params = $this->render_datafields($this->params); // Execute the provided function name passing with the given parameters. - $response = self::call_external_function($functionname, json_decode($params, true)); + $response = external_api::call_external_function($functionname, json_decode($params, true)); return $response; } @@ -150,12 +150,11 @@ public function execute($step, $trigger, $event, $stepresults) { try { $response = $this->run_function(); if ($response['error']) { - - // Throw an error if step results are not being returned. - $stepresults['error'] = json_encode($response['exception']); - - return [false, $stepresults]; + // Throw an exception to be propagated for proper error capture. + throw new \coding_exception(json_encode($response['exception'])); } + + $status = [true, $response]; } catch (\Throwable $e) { // Restore the previous user to avoid any side-effects occuring in later steps / code. \core\session\manager::set_user($previoususer); @@ -175,8 +174,8 @@ public function execute($step, $trigger, $event, $stepresults) { \core\session\manager::set_user($previoususer); $SESSION = $session; - // Return stepresults. - return [true, $stepresults]; + // Return the function call response as is. The shape is already normalised. + return $status; } /** @@ -202,12 +201,6 @@ public function form_definition_extra($form, $mform, $customdata) { $mform->addElement('textarea', 'params', get_string('webserviceactionparams', 'tool_trigger'), $attributes); $mform->setType('params', PARAM_RAW_TRIMMED); $mform->addHelpButton('params', 'webserviceactionparams', 'tool_trigger'); - - // Params. - $attributes = ['cols' => '50', 'rows' => '5']; - $mform->addElement('textarea', 'alphaparams', get_string('webserviceactionalphaparmas', 'tool_trigger'), $attributes); - $mform->setType('alphaparams', PARAM_RAW_TRIMMED); - $mform->addHelpButton('alphaparams', 'webserviceactionalphaparmas', 'tool_trigger'); } /** @@ -257,14 +250,9 @@ public function form_validation($data, $files) { $errorfield = 'params'; - $alphaparams = explode(',', $data['alphaparams']); - // Fill template fields with a number. Some params are special and only allow letters. - $transformcallback = function($matches) use($alphaparams) { - if (in_array($matches[1], $alphaparams)) { - return ''; - } else { - return 0; - } + // Fill template fields with a number. + $transformcallback = function() { + return 0; }; // Cannot use redner_datafields since we need to know of the @@ -336,106 +324,4 @@ public function transform_form_data($data) { } return $data; } - - /** - * Call an external function validating all params/returns correctly. - * - * Note that an external function may modify the state of the current page, so this wrapper - * saves and restores tha PAGE and COURSE global variables before/after calling the external function. - * This is a fork of the external_api::call_external_function method. - * Due the nature of the WS API, without a real user session the function may not work as expected. - * - * @param string $function A webservice function name. - * @param array $args Params array (named params) - * @param boolean $ajaxonly If true, an extra check will be peformed to see if ajax is required. - * @return array containing keys for error (bool), exception and data. - */ - public static function call_external_function($function, $args, $ajaxonly=false) { - global $PAGE, $COURSE, $CFG, $SITE; - - require_once($CFG->libdir . "/pagelib.php"); - - $externalfunctioninfo = \external_api::external_function_info($function); - - // Eventually this should shift into the various handlers and not be handled via config. - $readonlysession = $externalfunctioninfo->readonlysession ?? false; - - if (!$readonlysession || empty($CFG->enable_read_only_sessions)) { - \core\session\manager::restart_with_write_lock($readonlysession); - } - - $currentpage = $PAGE; - $currentcourse = $COURSE; - $response = array(); - - try { - // Taken straight from from setup.php. - if (!empty($CFG->moodlepageclass)) { - if (!empty($CFG->moodlepageclassfile)) { - require_once($CFG->moodlepageclassfile); - } - $classname = $CFG->moodlepageclass; - } else { - $classname = 'moodle_page'; - } - - $PAGE = new $classname(); - $COURSE = clone($SITE); - - // Validate params, this also sorts the params properly, we need the correct order in the next part. - $callable = array($externalfunctioninfo->classname, 'validate_parameters'); - - $params = call_user_func($callable, - $externalfunctioninfo->parameters_desc, - $args); - - $params = array_values($params); - // Allow any Moodle plugin a chance to override this call. This is a convenient spot to - // make arbitrary behaviour customisations. The overriding plugin could call the 'real' - // function first and then modify the results, or it could do a completely separate - // thing. - $callbacks = get_plugins_with_function('override_webservice_execution'); - $result = false; - - foreach ($callbacks as $plugintype => $plugins) { - foreach ($plugins as $plugin => $callback) { - $result = $callback($externalfunctioninfo, $params); - if ($result !== false) { - break 2; - } - } - } - - // If the function was not overridden, call the real one. - if ($result === false) { - $callable = array($externalfunctioninfo->classname, $externalfunctioninfo->methodname); - $result = call_user_func_array($callable, $params); - } - - // Validate the return parameters. - if ($externalfunctioninfo->returns_desc !== null) { - $callable = array($externalfunctioninfo->classname, 'clean_returnvalue'); - $result = call_user_func($callable, $externalfunctioninfo->returns_desc, $result); - } - - $response['error'] = false; - $response['data'] = $result; - } catch (\Throwable $e) { - $exception = get_exception_info($e); - unset($exception->a); - $exception->backtrace = format_backtrace($exception->backtrace, true); - if (!debugging('', DEBUG_DEVELOPER)) { - unset($exception->debuginfo); - unset($exception->backtrace); - } - $response['error'] = true; - $response['exception'] = $exception; - // Do not process the remaining requests. - } - - $PAGE = $currentpage; - $COURSE = $currentcourse; - - return $response; - } } diff --git a/lang/en/tool_trigger.php b/lang/en/tool_trigger.php index b12951e..e689ae9 100644 --- a/lang/en/tool_trigger.php +++ b/lang/en/tool_trigger.php @@ -292,8 +292,6 @@ $string['webserviceactionfunctionname'] = 'Function'; $string['webserviceactionfunctionname_help'] = 'The webservice function to be called. See the API Documentation'; -$string['webserviceactionalphaparmas'] = 'WS alpha parameters'; -$string['webserviceactionalphaparmas_help'] = 'The form validation may fail due to some ws parameters type, if you are getting an "ALPHA" type error, add the parameter here.'; $string['webserviceactionusername'] = 'Who'; $string['webserviceactionusername_help'] = 'The user (username) who this step will be performed in the context of. This defaults to the main admin user if not explicitly set'; $string['webserviceactionparams'] = 'Parameters'; diff --git a/tests/course_lookup_step_test.php b/tests/course_lookup_step_test.php index ac21c1c..b8ee165 100644 --- a/tests/course_lookup_step_test.php +++ b/tests/course_lookup_step_test.php @@ -90,6 +90,35 @@ public function test_execute_basic() { $this->assertEquals($context->id, $stepresults['course_contextid']); } + /** + * Basic test, but this time with additional custom course field. + */ + public function test_execute_basic_with_custom_profile_fields() { + // Create custom course field. + $customfieldg = $this->getDataGenerator()->get_plugin_generator('core_customfield'); + $category = $customfieldg->create_category(); + $customfield = $customfieldg->create_field([ + 'categoryid' => $category->get('id'), + 'type' => 'text', + 'shortname' => 'testfield1', + 'configdata' => [], + ]); + + // Add data to the customfield_data table. + $this->add_course_custom_course_field_data($customfield->get('id'), $this->course->id, 'CourseFieldValue'); + $step = new \tool_trigger\steps\lookups\course_lookup_step( + json_encode([ + 'courseidfield' => 'objectid', + 'outputprefix' => 'course_' + ]) + ); + + list($status, $stepresults) = $step->execute(null, null, $this->event, []); + $this->assertTrue($status); + // Check that the custom field data is returned as a step result. + $this->assertEquals('CourseFieldValue', $stepresults['course_testfield1']); + } + /** * Test for exception if an invalid field name is entered. */ @@ -222,4 +251,22 @@ public function test_execute_course_id_string() { $this->assertEquals($this->course->fullname, $stepresults['course_fullname']); $this->assertEquals($context->id, $stepresults['course_contextid']); } + + public function add_course_custom_course_field_data($fieldid, $courseid, $customfielddata) { + global $DB; + + // Add data to the customfield_data table. + $data = new \stdClass(); + $data->fieldid = $fieldid; + $data->instanceid = $courseid; + $data->value = $customfielddata; + $data->charvalue = $customfielddata; + $data->timecreated = time(); + $data->timemodified = time(); + $data->valueformat = 0; + $data->valuetrust = 0; + $data->contextid = \context_course::instance($courseid)->id; + + return $DB->insert_record('customfield_data', $data); + } }