/**
     * Perform an Outcomes service request.
     *
     * @param int $action The action type constant
     * @param LTI_Outcome $lti_outcome Outcome object
     * @param LTI_User $user User object
     *
     * @return boolean True if the request was successfully processed
     */
    public function doOutcomesService($action, $lti_outcome, $user = NULL)
    {
        $response = FALSE;
        $this->ext_response = NULL;
        #
        ### Lookup service details from the source resource link appropriate to the user (in case the destination is being shared)
        #
        $source_resource_link = $this;
        $sourcedid = $lti_outcome->getSourcedid();
        if (!is_null($user)) {
            $source_resource_link = $user->getResourceLink();
            $sourcedid = $user->lti_result_sourcedid;
        }
        #
        ### Use LTI 1.1 service in preference to extension service if it is available
        #
        $urlLTI11 = $source_resource_link->getSetting('lis_outcome_service_url');
        $urlExt = $source_resource_link->getSetting('ext_ims_lis_basic_outcome_url');
        if ($urlExt || $urlLTI11) {
            switch ($action) {
                case self::EXT_READ:
                    if ($urlLTI11 && $lti_outcome->type == self::EXT_TYPE_DECIMAL) {
                        $do = 'readResult';
                    } else {
                        if ($urlExt) {
                            $urlLTI11 = NULL;
                            $do = 'basic-lis-readresult';
                        }
                    }
                    break;
                case self::EXT_WRITE:
                    if ($urlLTI11 && $this->checkValueType($lti_outcome, array(self::EXT_TYPE_DECIMAL))) {
                        $do = 'replaceResult';
                    } else {
                        if ($this->checkValueType($lti_outcome)) {
                            $urlLTI11 = NULL;
                            $do = 'basic-lis-updateresult';
                        }
                    }
                    break;
                case self::EXT_DELETE:
                    if ($urlLTI11 && $lti_outcome->type == self::EXT_TYPE_DECIMAL) {
                        $do = 'deleteResult';
                    } else {
                        if ($urlExt) {
                            $urlLTI11 = NULL;
                            $do = 'basic-lis-deleteresult';
                        }
                    }
                    break;
            }
        }
        if (isset($do)) {
            $value = $lti_outcome->getValue();
            if (is_null($value)) {
                $value = '';
            }
            if ($urlLTI11) {
                $xml = '';
                if ($action == self::EXT_WRITE) {
                    $xml = <<<EOF

\t\t\t\t<result>
\t\t\t\t\t<resultScore>
\t\t\t\t\t\t<language>{$lti_outcome->language}</language>
\t\t\t\t\t\t<textString>{$value}</textString>
\t\t\t\t\t</resultScore>
\t\t\t\t</result>
EOF;
                }
                $sourcedid = htmlentities($sourcedid);
                $xml = <<<EOF
\t\t\t<resultRecord>
\t\t\t\t<sourcedGUID>
\t\t\t\t\t<sourcedId>{$sourcedid}</sourcedId>
\t\t\t\t</sourcedGUID>{$xml}
\t\t\t</resultRecord>
EOF;
                if ($this->doLTI11Service($do, $urlLTI11, $xml)) {
                    switch ($action) {
                        case self::EXT_READ:
                            if (!isset($this->ext_nodes['imsx_POXBody']["{$do}Response"]['result']['resultScore']['textString'])) {
                                break;
                            } else {
                                $lti_outcome->setValue($this->ext_nodes['imsx_POXBody']["{$do}Response"]['result']['resultScore']['textString']);
                            }
                        case self::EXT_WRITE:
                        case self::EXT_DELETE:
                            $response = TRUE;
                            break;
                    }
                }
            } else {
                $params = array();
                $params['sourcedid'] = $sourcedid;
                $params['result_resultscore_textstring'] = $value;
                if (!empty($lti_outcome->language)) {
                    $params['result_resultscore_language'] = $lti_outcome->language;
                }
                if (!empty($lti_outcome->status)) {
                    $params['result_statusofresult'] = $lti_outcome->status;
                }
                if (!empty($lti_outcome->date)) {
                    $params['result_date'] = $lti_outcome->date;
                }
                if (!empty($lti_outcome->type)) {
                    $params['result_resultvaluesourcedid'] = $lti_outcome->type;
                }
                if (!empty($lti_outcome->data_source)) {
                    $params['result_datasource'] = $lti_outcome->data_source;
                }
                if ($this->doService($do, $urlExt, $params)) {
                    switch ($action) {
                        case self::EXT_READ:
                            if (isset($this->ext_nodes['result']['resultscore']['textstring'])) {
                                $response = $this->ext_nodes['result']['resultscore']['textstring'];
                            }
                            break;
                        case self::EXT_WRITE:
                        case self::EXT_DELETE:
                            $response = TRUE;
                            break;
                    }
                }
            }
            if (is_array($response) && count($response) <= 0) {
                $response = '';
            }
        }
        return $response;
    }