public function internal_get_state($cm, $userid, $current) {
        global $USER, $DB, $CFG;

        // Get user ID
        if (!$userid) {
            $userid = $USER->id;
        }

        // Check viewed
        if ($cm->completionview == COMPLETION_VIEW_REQUIRED &&
            $current->viewed == COMPLETION_NOT_VIEWED) {

            return COMPLETION_INCOMPLETE;
        }

        // Modname hopefully is provided in $cm but just in case it isn't, let's grab it
        if (!isset($cm->modname)) {
            $cm->modname = $DB->get_field('modules', 'name', array('id'=>$cm->module));
        }

        $newstate = COMPLETION_COMPLETE;

        // Check grade
        if (!is_null($cm->completiongradeitemnumber)) {
            require_once($CFG->libdir.'/gradelib.php');
            $item = grade_item::fetch(array('courseid'=>$cm->course, 'itemtype'=>'mod',
                'itemmodule'=>$cm->modname, 'iteminstance'=>$cm->instance,
                'itemnumber'=>$cm->completiongradeitemnumber));
            if ($item) {
                // Fetch 'grades' (will be one or none)
                $grades = grade_grade::fetch_users_grades($item, array($userid), false);
                if (empty($grades)) {
                    // No grade for user
                    return COMPLETION_INCOMPLETE;
                }
                if (count($grades) > 1) {
                    $this->internal_systemerror("Unexpected result: multiple grades for
                        item '{$item->id}', user '{$userid}'");
                }
                $newstate = self::internal_get_grade_state($item, reset($grades));
                if ($newstate == COMPLETION_INCOMPLETE) {
                    return COMPLETION_INCOMPLETE;
                }

            } else {
                $this->internal_systemerror("Cannot find grade item for '{$cm->modname}'
                    cm '{$cm->id}' matching number '{$cm->completiongradeitemnumber}'");
            }
        }

        if (plugin_supports('mod', $cm->modname, FEATURE_COMPLETION_HAS_RULES)) {
            $function = $cm->modname.'_get_completion_state';
            if (!function_exists($function)) {
                $this->internal_systemerror("Module {$cm->modname} claims to support
                    FEATURE_COMPLETION_HAS_RULES but does not have required
                    {$cm->modname}_get_completion_state function");
            }
            if (!$function($this->course, $cm, $userid, COMPLETION_AND)) {
                return COMPLETION_INCOMPLETE;
            }
        }

        return $newstate;

    }