public function search(\stdClass $formdata, $limit = 0) {
        // For Behat testing, the search results can be faked using a special step.
        if (defined('BEHAT_SITE_RUNNING')) {
            $fakeresult = get_config('core_search', 'behat_fakeresult');
            if ($fakeresult) {
                // Clear config setting.
                unset_config('core_search', 'behat_fakeresult');

                // Check query matches expected value.
                $details = json_decode($fakeresult);
                if ($formdata->q !== $details->query) {
                    throw new \coding_exception('Unexpected search query: ' . $formdata->q);
                }

                // Create search documents from the JSON data.
                $docs = [];
                foreach ($details->results as $result) {
                    $doc = new \core_search\document($result->itemid, $result->componentname,
                            $result->areaname);
                    foreach ((array)$result->fields as $field => $value) {
                        $doc->set($field, $value);
                    }
                    foreach ((array)$result->extrafields as $field => $value) {
                        $doc->set_extra($field, $value);
                    }
                    $area = $this->get_search_area($doc->get('areaid'));
                    $doc->set_doc_url($area->get_doc_url($doc));
                    $doc->set_context_url($area->get_context_url($doc));
                    $docs[] = $doc;
                }

                return $docs;
            }
        }

        $limitcourseids = $this->build_limitcourseids($formdata);

        $limitcontextids = false;
        if (!empty($formdata->contextids)) {
            $limitcontextids = $formdata->contextids;
        }

        // Clears previous query errors.
        $this->engine->clear_query_error();

        $contextinfo = $this->get_areas_user_accesses($limitcourseids, $limitcontextids);
        if (!$contextinfo->everything && !$contextinfo->usercontexts) {
            // User can not access any context.
            $docs = array();
        } else {
            // If engine does not support groups, remove group information from the context info -
            // use the old format instead (true = admin, array = user contexts).
            if (!$this->engine->supports_group_filtering()) {
                $contextinfo = $contextinfo->everything ? true : $contextinfo->usercontexts;
            }

            // Execute the actual query.
            $docs = $this->engine->execute_query($formdata, $contextinfo, $limit);
        }

        return $docs;
    }