From 488244d12d6cd4b75d092246125246dbe414b110 Mon Sep 17 00:00:00 2001
From: ferran <ferranrecio@gmail.com>
Date: Fri, 7 Feb 2025 17:54:22 +0100
Subject: [PATCH] MDL-84469 core_course: add fallback activity overview

---
 .../local/overview/resourceoverview.php       |  12 ++
 .../local/overview/missingoverviewnotice.php  | 113 ++++++++++++++++++
 .../output/local/overview/overviewpage.php    |  62 ----------
 .../overview/missingoverviewnotice.mustache   |  39 ++++++
 .../local/overview/overviewpage.mustache      |  17 ---
 .../local/overview/overviewfactory_test.php   |  70 ++++++++++-
 .../local/overview/resourceoverview_test.php  |  65 +++++++++-
 .../overview/missingoverviewnotice_test.php   |  90 ++++++++++++++
 course/lib.php                                |   6 +
 course/tests/behat/course_overview.feature    |  71 +++++++++--
 lang/en/course.php                            |   4 +-
 11 files changed, 455 insertions(+), 94 deletions(-)
 create mode 100644 course/format/classes/output/local/overview/missingoverviewnotice.php
 create mode 100644 course/format/templates/local/overview/missingoverviewnotice.mustache
 create mode 100644 course/format/tests/output/local/overview/missingoverviewnotice_test.php

diff --git a/course/format/classes/local/overview/resourceoverview.php b/course/format/classes/local/overview/resourceoverview.php
index 4889291c435..66afb25a9c4 100644
--- a/course/format/classes/local/overview/resourceoverview.php
+++ b/course/format/classes/local/overview/resourceoverview.php
@@ -37,6 +37,18 @@ class resourceoverview extends \core_courseformat\activityoverviewbase {
      * @return overviewitem|null
      */
     private function get_extra_type_overview(): ?overviewitem {
+        // Only resource activities shows the type overview
+        // because they are aggregated in one table.
+        $archetype = plugin_supports(
+            type: 'mod',
+            name: $this->cm->modname,
+            feature: FEATURE_MOD_ARCHETYPE,
+            default: MOD_ARCHETYPE_OTHER
+        );
+        if ($archetype != MOD_ARCHETYPE_RESOURCE) {
+            return null;
+        }
+
         return new overviewitem(
             name: get_string('resource_type'),
             value: $this->cm->modfullname,
diff --git a/course/format/classes/output/local/overview/missingoverviewnotice.php b/course/format/classes/output/local/overview/missingoverviewnotice.php
new file mode 100644
index 00000000000..7573c7de366
--- /dev/null
+++ b/course/format/classes/output/local/overview/missingoverviewnotice.php
@@ -0,0 +1,113 @@
+<?php
+// This file is part of Moodle - http://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 <http://www.gnu.org/licenses/>.
+
+namespace core_courseformat\output\local\overview;
+
+use core\output\action_link;
+use core\output\named_templatable;
+use core\output\renderable;
+use core\output\notification;
+use core\plugin_manager;
+use core\url;
+use stdClass;
+
+/**
+ * Class missingoverviewnotice
+ *
+ * @package    core_courseformat
+ * @copyright  2025 Ferran Recio <ferran@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class missingoverviewnotice implements renderable, named_templatable {
+    /**
+     * Constructor.
+     *
+     * @param stdClass $course The course object.
+     * @param string $modname The module name.
+     */
+    public function __construct(
+        /** @var stdClass $course the course object  */
+        private stdClass $course,
+        /** @var string $modname the activity module name  */
+        private string $modname,
+    ) {
+    }
+
+    #[\Override]
+    public function export_for_template(\renderer_base $output): stdClass {
+        if (!$this->activity_has_overview_integration($this->modname)) {
+            return $this->export_legacy_overview($output);
+        }
+        // The notice is not needed for plugins with overview class.
+        return (object) [];
+    }
+
+    /**
+     * Checks if a given activity module has an overview integration.
+     *
+     * The method search for an integration class named `\mod_{modname}\course\overview`.
+     *
+     * @param string $modname The name of the activity module.
+     * @return bool True if the activity module has an overview integration, false otherwise.
+     */
+    private function activity_has_overview_integration(string $modname): bool {
+        $classname = 'mod_' . $modname . '\courseformat\overview';
+        if ($modname === 'resource') {
+            $classname = 'core_courseformat\local\overview\resourceoverview';
+        }
+        return class_exists($classname);
+    }
+
+    /**
+     * Exports the legacy overview for a given module.
+     *
+     * This export only applies to modules that do not have an overview integration.
+     *
+     * @param \renderer_base $output
+     * @return stdClass
+     */
+    private function export_legacy_overview(
+        \renderer_base $output,
+    ): stdClass {
+        $legacyoverview = '/mod/' . $this->modname . '/index.php';
+        $name = plugin_manager::instance()->plugin_name($this->modname);
+
+        $link = new action_link(
+            url: new url($legacyoverview, ['id' => $this->course->id]),
+            text: get_string('overview_modname', 'core_course', $name),
+        );
+
+        $notification = new notification(
+            message: get_string('overview_missing_notice', 'core_course', $output->render($link)),
+            messagetype: notification::NOTIFY_INFO,
+            closebutton: false,
+            title: get_string('overview_missing_title', 'core_course', $name),
+            titleicon: 'i/circleinfo',
+        );
+
+        return (object) [
+            'name' => $name,
+            'shortname' => $this->modname,
+            'notification' => $notification->export_for_template($output),
+            'missingoverview' => true,
+        ];
+    }
+
+    #[\Override]
+    public function get_template_name(\renderer_base $renderer): string {
+        return 'core_courseformat/local/overview/missingoverviewnotice';
+    }
+}
diff --git a/course/format/classes/output/local/overview/overviewpage.php b/course/format/classes/output/local/overview/overviewpage.php
index 290ceb274b0..72f4a8e9fb5 100644
--- a/course/format/classes/output/local/overview/overviewpage.php
+++ b/course/format/classes/output/local/overview/overviewpage.php
@@ -138,10 +138,6 @@ class overviewpage implements renderable, named_templatable {
         string $modname,
         string $modfullname
     ): stdClass {
-        if (!$this->activity_has_overview_integration($modname)) {
-            return $this->export_legacy_overview($output, $modname, $modfullname);
-        }
-
         return (object) [
             'fragment' => $this->export_overview_fragment($modname),
             'icon' => $this->get_activity_overview_icon($output, $modname),
@@ -165,64 +161,6 @@ class overviewpage implements renderable, named_templatable {
         return $output->pix_icon('monologo', '', "mod_$modname", ['class' => 'icon iconsize-medium']);
     }
 
-    /**
-     * Exports the legacy overview for a given module.
-     *
-     * This export only applies to modules that do not have an overview integration.
-     *
-     * @param \renderer_base $output
-     * @param string $modname
-     * @param string $modfullname
-     * @return stdClass
-     */
-    private function export_legacy_overview(
-        \renderer_base $output,
-        string $modname,
-        string $modfullname
-    ): stdClass {
-        if ($modname === 'resource') {
-            $legacyoverview = 'resources.php';
-            $message = get_string('overview_missing_title', 'core_course', get_string('resource'));
-        } else {
-            $legacyoverview = '/mod/' . $modname . '/index.php';
-            $pluginman = plugin_manager::instance();
-            $message = get_string('overview_missing_title', 'core_course', $pluginman->plugin_name($modname));
-        }
-
-        $notification = new notification(
-            message: get_string('overview_missing_notice', 'core_course'),
-            messagetype: \core\notification::INFO,
-            closebutton: false,
-            title: $message,
-            titleicon: 'i/circleinfo',
-        );
-
-        return (object)[
-            'overviewurl' => new url($legacyoverview, ['id' => $this->course->id]),
-            'icon' => $this->get_activity_overview_icon($output, $modname),
-            'name' => $modfullname,
-            'shortname' => $modname,
-            'notification' => $notification->export_for_template($output),
-            'open' => in_array($modname, $this->expanded),
-        ];
-    }
-
-    /**
-     * Checks if a given activity module has an overview integration.
-     *
-     * The method search for an integration class named `\mod_{modname}\courseformat\overview`.
-     *
-     * @param string $modname The name of the activity module.
-     * @return bool True if the activity module has an overview integration, false otherwise.
-     */
-    private function activity_has_overview_integration(string $modname): bool {
-        $classname = 'mod_' . $modname . '\courseformat\overview';
-        if ($modname === 'resource') {
-            $classname = 'core_courseformat\local\overview\resourceoverview';
-        }
-        return class_exists($classname);
-    }
-
     /**
      * Exports an overview fragment for a given module name.
      *
diff --git a/course/format/templates/local/overview/missingoverviewnotice.mustache b/course/format/templates/local/overview/missingoverviewnotice.mustache
new file mode 100644
index 00000000000..58b83cad9b1
--- /dev/null
+++ b/course/format/templates/local/overview/missingoverviewnotice.mustache
@@ -0,0 +1,39 @@
+{{!
+    This file is part of Moodle - http://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 <http://www.gnu.org/licenses/>.
+}}
+{{!
+    @template core_courseformat/local/overview/missingoverviewnotice
+
+    Message to display when the activity plugin overview is missing.
+
+    Example context (json):
+    {
+        "name": "Course name",
+        "overviewurl": "https://moodle.org",
+        "notification": {
+            "message": "Notification message",
+            "level": "info"
+        },
+        "missingoverview": true
+    }
+}}
+{{#missingoverview}}
+<div class="d-flex flex-column justify-content-between mb-3">
+    {{#notification}}
+        {{>core/notification_info}}
+    {{/notification}}
+</div>
+{{/missingoverview}}
diff --git a/course/format/templates/local/overview/overviewpage.mustache b/course/format/templates/local/overview/overviewpage.mustache
index 54735ff7f1d..1a4dabb80e2 100644
--- a/course/format/templates/local/overview/overviewpage.mustache
+++ b/course/format/templates/local/overview/overviewpage.mustache
@@ -59,23 +59,6 @@
                 </div>
                 {{/preloadedcontent}}
             {{/fragment}}
-            {{^fragment}}
-            <div class="d-flex flex-column justify-content-between">
-                {{#notification}}
-                    {{>core/notification_info}}
-                {{/notification}}
-                <div>
-                    <a
-                        class="btn btn-outline-secondary"
-                        href="{{overviewurl}}"
-                        role="button"
-                    >
-                        {{#str}} goto_overview, course, {{name}} {{/str}}
-                        <span class="ms-2">{{#pix}} i/arrow-right, core {{/pix}}</span>
-                    </a>
-                </div>
-            </div>
-            {{/fragment}}
         {{/sectioncontent}}
     {{/core/local/collapsable_section}}
     {{/elements}}
diff --git a/course/format/tests/local/overview/overviewfactory_test.php b/course/format/tests/local/overview/overviewfactory_test.php
index 76e845823fb..bf94583a241 100644
--- a/course/format/tests/local/overview/overviewfactory_test.php
+++ b/course/format/tests/local/overview/overviewfactory_test.php
@@ -42,6 +42,7 @@ final class overviewfactory_test extends \advanced_testcase {
      */
     public function test_create_resource(
         string $resourcetype,
+        ?string $expected,
     ): void {
         $this->resetAfterTest();
         $this->setAdminUser();
@@ -54,7 +55,7 @@ final class overviewfactory_test extends \advanced_testcase {
 
         $overview = overviewfactory::create($cm);
 
-        $this->assertInstanceOf(resourceoverview::class, $overview);
+        $this->assertInstanceOf($expected, $overview);
     }
 
     /**
@@ -64,20 +65,87 @@ final class overviewfactory_test extends \advanced_testcase {
      */
     public static function create_resource_provider(): array {
         return [
+            // Resource activities.
             'book' => [
                 'resourcetype' => 'book',
+                'expected' => resourceoverview::class,
             ],
             'folder' => [
                 'resourcetype' => 'folder',
+                'expected' => resourceoverview::class,
             ],
             'page' => [
                 'resourcetype' => 'page',
+                'expected' => resourceoverview::class,
             ],
             'resource' => [
                 'resourcetype' => 'resource',
+                'expected' => resourceoverview::class,
             ],
             'url' => [
                 'resourcetype' => 'url',
+                'expected' => resourceoverview::class,
+            ],
+            // Fallbacks and integrations.
+            'assign' => [
+                'resourcetype' => 'assign',
+                'expected' => \mod_assign\courseformat\overview::class,
+            ],
+            'bigbluebuttonbn' => [
+                'resourcetype' => 'bigbluebuttonbn',
+                'expected' => resourceoverview::class,
+            ],
+            'choice' => [
+                'resourcetype' => 'choice',
+                'expected' => resourceoverview::class,
+            ],
+            'data' => [
+                'resourcetype' => 'data',
+                'expected' => resourceoverview::class,
+            ],
+            'feedback' => [
+                'resourcetype' => 'feedback',
+                'expected' => \mod_feedback\courseformat\overview::class,
+            ],
+            'forum' => [
+                'resourcetype' => 'forum',
+                'expected' => resourceoverview::class,
+            ],
+            'glossary' => [
+                'resourcetype' => 'glossary',
+                'expected' => resourceoverview::class,
+            ],
+            'h5pactivity' => [
+                'resourcetype' => 'h5pactivity',
+                'expected' => resourceoverview::class,
+            ],
+            'lesson' => [
+                'resourcetype' => 'lesson',
+                'expected' => resourceoverview::class,
+            ],
+            'lti' => [
+                'resourcetype' => 'lti',
+                'expected' => resourceoverview::class,
+            ],
+            'qbank' => [
+                'resourcetype' => 'qbank',
+                'expected' => resourceoverview::class,
+            ],
+            'quiz' => [
+                'resourcetype' => 'quiz',
+                'expected' => resourceoverview::class,
+            ],
+            'scorm' => [
+                'resourcetype' => 'scorm',
+                'expected' => resourceoverview::class,
+            ],
+            'wiki' => [
+                'resourcetype' => 'wiki',
+                'expected' => resourceoverview::class,
+            ],
+            'workshop' => [
+                'resourcetype' => 'workshop',
+                'expected' => resourceoverview::class,
             ],
         ];
     }
diff --git a/course/format/tests/local/overview/resourceoverview_test.php b/course/format/tests/local/overview/resourceoverview_test.php
index cf97591a10e..830e9e23bc0 100644
--- a/course/format/tests/local/overview/resourceoverview_test.php
+++ b/course/format/tests/local/overview/resourceoverview_test.php
@@ -56,9 +56,11 @@ final class resourceoverview_test extends \advanced_testcase {
      * @covers ::get_extra_type_overview
      * @dataProvider get_extra_type_overview_provider
      * @param string $resourcetype
+     * @param string|null $expected
      */
     public function test_get_extra_type_overview(
         string $resourcetype,
+        ?string $expected,
     ): void {
         $this->resetAfterTest();
         $this->setAdminUser();
@@ -74,9 +76,14 @@ final class resourceoverview_test extends \advanced_testcase {
         $items = $overview->get_extra_overview_items();
         $result = $items['type'];
 
+        if ($expected === null) {
+            $this->assertNull($result);
+            return;
+        }
+
         $this->assertEquals(get_string('resource_type'), $result->get_name());
-        $this->assertEquals($cm->modfullname, $result->get_value());
-        $this->assertEquals($cm->modfullname, $result->get_content());
+        $this->assertEquals($expected, $result->get_value());
+        $this->assertEquals($expected, $result->get_content());
     }
 
     /**
@@ -88,18 +95,72 @@ final class resourceoverview_test extends \advanced_testcase {
         return [
             'book' => [
                 'resourcetype' => 'book',
+                'expected' => 'Book',
             ],
             'folder' => [
                 'resourcetype' => 'folder',
+                'expected' => 'Folder',
             ],
             'page' => [
                 'resourcetype' => 'page',
+                'expected' => 'Page',
             ],
             'resource' => [
                 'resourcetype' => 'resource',
+                'expected' => 'File',
             ],
             'url' => [
                 'resourcetype' => 'url',
+                'expected' => 'URL',
+            ],
+            // Activities without integration.
+            'bigbluebuttonbn' => [
+                'resourcetype' => 'bigbluebuttonbn',
+                'expected' => null,
+            ],
+            'choice' => [
+                'resourcetype' => 'choice',
+                'expected' => null,
+            ],
+            'data' => [
+                'resourcetype' => 'data',
+                'expected' => null,
+            ],
+            'forum' => [
+                'resourcetype' => 'forum',
+                'expected' => null,
+            ],
+            'glossary' => [
+                'resourcetype' => 'glossary',
+                'expected' => null,
+            ],
+            'h5pactivity' => [
+                'resourcetype' => 'h5pactivity',
+                'expected' => null,
+            ],
+            'lesson' => [
+                'resourcetype' => 'lesson',
+                'expected' => null,
+            ],
+            'lti' => [
+                'resourcetype' => 'lti',
+                'expected' => null,
+            ],
+            'qbank' => [
+                'resourcetype' => 'qbank',
+                'expected' => null,
+            ],
+            'quiz' => [
+                'resourcetype' => 'quiz',
+                'expected' => null,
+            ],
+            'scorm' => [
+                'resourcetype' => 'scorm',
+                'expected' => null,
+            ],
+            'wiki' => [
+                'resourcetype' => 'wiki',
+                'expected' => null,
             ],
         ];
     }
diff --git a/course/format/tests/output/local/overview/missingoverviewnotice_test.php b/course/format/tests/output/local/overview/missingoverviewnotice_test.php
new file mode 100644
index 00000000000..241e33c3cdc
--- /dev/null
+++ b/course/format/tests/output/local/overview/missingoverviewnotice_test.php
@@ -0,0 +1,90 @@
+<?php
+// This file is part of Moodle - http://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 <http://www.gnu.org/licenses/>.
+
+namespace core_courseformat\output\local\overview;
+
+/**
+ * Tests for courseformat
+ *
+ * @package    core_courseformat
+ * @category   test
+ * @copyright  2025 Ferran Recio <ferran@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @covers     \core_courseformat\output\local\overview\missingoverviewnotice
+ */
+final class missingoverviewnotice_test extends \advanced_testcase {
+    /**
+     * Test overview integrations.
+     *
+     * @covers ::export_for_template
+     * @covers ::activity_has_overview_integration
+     * @dataProvider overview_integrations_provider
+     * @param string $modname
+     * @param bool $expectempty
+     */
+    public function test_overview_integrations(
+        string $modname,
+        bool $expectempty,
+    ): void {
+        global $PAGE;
+
+        $this->resetAfterTest();
+
+        $renderer = $PAGE->get_renderer('core');
+        $course = $this->getDataGenerator()->create_course();
+
+        $missingoverviewnotice = new missingoverviewnotice($course, $modname);
+        $export = $missingoverviewnotice->export_for_template($renderer);
+
+        if ($expectempty) {
+            $this->assertEquals((object) [], $export);
+        } else {
+            $this->assertNotEquals((object) [], $export);
+        }
+    }
+
+    /**
+     * Data provider for test_overview_integrations.
+     *
+     * @return array
+     */
+    public static function overview_integrations_provider(): array {
+        return [
+            'assign' => ['modname' => 'assign', 'expectempty' => true],
+            'bigbluebuttonbn' => ['modname' => 'bigbluebuttonbn', 'expectempty' => false],
+            'book' => ['modname' => 'book', 'expectempty' => false],
+            'choice' => ['modname' => 'choice', 'expectempty' => false],
+            'data' => ['modname' => 'data', 'expectempty' => false],
+            'feedback' => ['modname' => 'feedback', 'expectempty' => true],
+            'folder' => ['modname' => 'folder', 'expectempty' => false],
+            'forum' => ['modname' => 'forum', 'expectempty' => false],
+            'glossary' => ['modname' => 'glossary', 'expectempty' => false],
+            'h5pactivity' => ['modname' => 'h5pactivity', 'expectempty' => false],
+            'imscp' => ['modname' => 'imscp', 'expectempty' => false],
+            'label' => ['modname' => 'label', 'expectempty' => false],
+            'lesson' => ['modname' => 'lesson', 'expectempty' => false],
+            'lti' => ['modname' => 'lti', 'expectempty' => false],
+            'page' => ['modname' => 'page', 'expectempty' => false],
+            'qbank' => ['modname' => 'qbank', 'expectempty' => false],
+            'quiz' => ['modname' => 'quiz', 'expectempty' => false],
+            'resource' => ['modname' => 'resource', 'expectempty' => true],
+            'scorm' => ['modname' => 'scorm', 'expectempty' => false],
+            'url' => ['modname' => 'url', 'expectempty' => false],
+            'wiki' => ['modname' => 'wiki', 'expectempty' => false],
+            'workshop' => ['modname' => 'workshop', 'expectempty' => false],
+        ];
+    }
+}
diff --git a/course/lib.php b/course/lib.php
index 3b53d422721..1557e5729bd 100644
--- a/course/lib.php
+++ b/course/lib.php
@@ -4868,6 +4868,12 @@ function course_output_fragment_course_overview($args) {
     $format = course_get_format($course);
     $renderer = $format->get_renderer($PAGE);
 
+    // Plugins with not implemented overview table will have an extra link to the index.php.
+    $overvietableclass = $format->get_output_classname('overview\missingoverviewnotice');
+    /** @var \core_courseformat\output\local\overview\missingoverviewnotice $output */
+    $output = new $overvietableclass($course, $modname);
+    $content .= $renderer->render($output);
+
     $overvietableclass = $format->get_output_classname('overview\\overviewtable');
     /** @var \core_courseformat\output\local\overview\overviewtable $output */
     $output = new $overvietableclass($course, $modname);
diff --git a/course/tests/behat/course_overview.feature b/course/tests/behat/course_overview.feature
index 34a000ba0bc..16d60bedc02 100644
--- a/course/tests/behat/course_overview.feature
+++ b/course/tests/behat/course_overview.feature
@@ -20,14 +20,14 @@ Feature: Users can access the course activities overview page
       | activity | course | section | idnumber | name                 |
       | assign   | C1     | 1       | 1        | Test assignment name |
 
-  Scenario: Teacher can access the course overview page
+  Scenario: Teacher can navigate to the course overview page
     Given I am on the "C1" "Course" page logged in as "teacher1"
     When I follow "Activities"
     Then I should see "Activities"
     And I should see "View all the activities in this course" in the "region-main" "region"
     And I should see "Assignments" in the "region-main" "region"
 
-  Scenario: Student can access the course overview page
+  Scenario: Student can navigate to the course overview page
     Given I am on the "C1" "Course" page logged in as "student1"
     When I follow "Activities"
     Then I should see "Activities"
@@ -80,13 +80,13 @@ Feature: Users can access the course activities overview page
     And I should see "Assignments" in the "assign_overview_collapsible" "region"
     And I should see "Forums" in the "forum_overview_collapsible" "region"
     And I should not see "Test assignment name" in the "assign_overview_collapsible" "region"
-    And I should not see "Go to Forums overview" in the "forum_overview_collapsible" "region"
+    And I should not see "Forum overview page" in the "forum_overview_collapsible" "region"
     When I click on "Expand" "link" in the "assign_overview_collapsible" "region"
     Then I should see "Test assignment name" in the "assign_overview_collapsible" "region"
-    And I should not see "Go to Forums overview" in the "forum_overview_collapsible" "region"
+    And I should not see "Forum overview page" in the "forum_overview_collapsible" "region"
     And I click on "Collapse" "link" in the "assign_overview_collapsible" "region"
     And I should not see "Test assignment name" in the "assign_overview_collapsible" "region"
-    And I should not see "Go to Forums overview" in the "forum_overview_collapsible" "region"
+    And I should not see "Forum overview page" in the "forum_overview_collapsible" "region"
 
   Scenario: Course overview shows the course present activity types
     Given the following "activities" exist:
@@ -207,11 +207,11 @@ Feature: Users can access the course activities overview page
 
   Scenario: Students can see the automatic completion criterias in the course overview
     Given the following "activity" exists:
-      | activity | folder |
-      | name | Activity 1 |
-      | course         | C1              |
-      | completion     | 2               |
-      | completionview | 1               |
+      | activity       | folder     |
+      | name           | Activity 1 |
+      | course         | C1         |
+      | completion     | 2          |
+      | completionview | 1          |
     When I am on the "Course 1" "course > activities > resource" page logged in as "student1"
     Then I should see "To do" in the "Activity 1" "table_row"
     And I should see "View" in the "Activity 1" "table_row"
@@ -250,3 +250,54 @@ Feature: Users can access the course activities overview page
     And I click on "Get these logs" "button"
     Then I should see "Course activities overview page viewed"
     And I should see "viewed the list of resources"
+
+  Scenario: Users can see a link to the old index when the activity does not provide overview information
+    Given the following "activities" exist:
+      | activity | course | name       |
+      | wiki     | C1     | Activity 1 |
+      | wiki     | C1     | Activity 2 |
+      | assign   | C1     | Activity 3 |
+    When I am on the "Course 1" "course > activities > wiki" page logged in as "student1"
+    And I should see "Wiki overview page"
+    And I follow "Wiki overview"
+    And I should see "Activity 1"
+    And I should see "Activity 2"
+    # Check activities with integration do not show the link.
+    And I am on the "Course 1" "course > activities > assign" page
+    And I should not see "Assignment overview page"
+
+  Scenario: Activities overview provide completion information to the student
+    Given the following "activities" exist:
+      | activity | course | name       | completion | completionview |
+      | choice   | C1     | Activity 1 | 2          | 1              |
+      | choice   | C1     | Activity 2 | 2          | 1              |
+      | choice   | C1     | Activity 3 | 1          | 0              |
+      | choice   | C1     | Activity 4 | 0          | 0              |
+    And I am on the "Activity 1" "activity" page logged in as "student1"
+    When I am on the "Course 1" "course > activities > choice" page logged in as "student1"
+    Then I should see "Completion status" in the "choice_overview_collapsible" "region"
+    And I should see "Done" in the "Activity 1" "table_row"
+    And I should see "To do" in the "Activity 2" "table_row"
+    And I should see "Mark as done" in the "Activity 3" "table_row"
+    And I should see "-" in the "Activity 4" "table_row"
+    And I am on the "Course 1" "course > activities > choice" page logged in as "teacher1"
+    And I should not see "Completion status" in the "choice_overview_collapsible" "region"
+    And I should not see "To do" in the "Activity 2" "table_row"
+    And I should not see "Mark as done" in the "Activity 3" "table_row"
+    And I should not see "-" in the "Activity 4" "table_row"
+
+  Scenario: Activities overview provide grade information to the student
+    Given the following "activities" exist:
+      | activity | course | name       |
+      | lesson   | C1     | Activity 1 |
+      | lesson   | C1     | Activity 2 |
+    And I am on the "Course 1" "grades > Grader report > View" page logged in as "teacher1"
+    And I turn editing mode on
+    And I give the grade "42" to the user "Student 1" for the grade item "Activity 1"
+    And I press "Save changes"
+    When I am on the "Course 1" "course > activities > lesson" page logged in as "student1"
+    Then I should see "Grade" in the "lesson_overview_collapsible" "region"
+    And I should see "42.00" in the "Activity 1" "table_row"
+    And I should see "-" in the "Activity 2" "table_row"
+    When I am on the "Course 1" "course > activities > lesson" page logged in as "teacher1"
+    And I should not see "Grade" in the "lesson_overview_collapsible" "region"
diff --git a/lang/en/course.php b/lang/en/course.php
index 5154dd56fe4..68982b002eb 100644
--- a/lang/en/course.php
+++ b/lang/en/course.php
@@ -100,7 +100,6 @@ $string['filterbothactive'] = 'First ({$a->first}) Last ({$a->last})';
 $string['filterbyname'] = 'Filter by name';
 $string['filterfirstactive'] = 'First ({$a->first})';
 $string['filterlastactive'] = 'Last ({$a->last})';
-$string['goto_overview'] = 'Go to {$a} overview';
 $string['gradetopassnotset'] = 'This course does not have a grade to pass set. It may be set in the grade item of the course (Gradebook setup).';
 $string['hideendedcoursestask'] = 'Hide courses on end date';
 $string['informationformodule'] = 'Information about the {$a} activity';
@@ -117,8 +116,9 @@ $string['norecentaccessesinfomessage'] = 'Hi {$a->userfirstname},
 $string['noteachinginfomessage'] = 'Hi {$a->userfirstname},
 <p>Courses with start dates in the next week have been identified as having no teacher or student enrolments.</p>';
 $string['overview_info'] = 'View all the activities in this course, including key details like due date and updates.';
-$string['overview_missing_notice'] = 'Check the overview page for more details.';
+$string['overview_missing_notice'] = 'Go to {$a} for more details.';
 $string['overview_missing_title'] = 'Information not available here for {$a} activities';
+$string['overview_modname'] = '{$a} overview page';
 $string['overview_page_title'] = 'Course activities: {$a}';
 $string['overview_table_caption'] = 'Table listing all {$a} activities';
 $string['participants:perpage'] = 'Number of participants per page';