Skip to content

Assignments: Let teachers follow an assignment to receive learner comment e-mails - #9282

Merged
ywarnier merged 3 commits into
chamilo:masterfrom
ybtbeez:fix/issue-1407-assignment-follow
Oct 20, 2026
Merged

ywarnier merged 3 commits into
chamilo:masterfrom
ybtbeez:fix/issue-1407-assignment-follow

Conversation

@ybtbeez

@ybtbeez ybtbeez commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

Fixes #1407

Problem

When a learner commented on their own submission on the legacy page (main/work/view.php), every teacher of the course (or every coach of the session) got an e-mail, including teachers who had nothing to do with that assignment. The only way out was the course-wide setting email_to_teachers_on_new_work_feedback (cf2bd42, 2017), which turns the e-mails off for everybody. Comments posted from the newer Vue/API assignment screens notified no teacher at all.

What this PR does

Following an assignment is now a per-teacher choice, stored in its own table, and both comment paths use one shared service.

  • New table c_student_publication_follow (id, publication_id → c_student_publication.iid, user_id → user.id, created_at). It has a unique key on (publication, user) and ON DELETE CASCADE on both foreign keys. It comes with the entity CStudentPublicationFollow and CStudentPublicationFollowRepository. c_student_publication_rel_user is deliberately not reused: it lists the users an assignment is restricted to, and mixing both meanings would change who can see restricted assignments.

  • One notification path: AssignmentFeedbackNotifier.

    • Both the legacy addWorkComment() (work.lib.php) and CreateStudentPublicationCommentAction call it when a learner comments.
    • It e-mails only the followers of the assignment, using the same subject and body as before through MessageManager::send_message_simple(), so the inbox message and e-mail behave as they always did.
    • Followers who no longer teach the course are skipped, so an old follow row does not leak learner comments. A follower is told only if they are a platform admin, a teacher of the course, or a coach of the session the comment was made in (course coach of that course in that session, or its general coach, and only when the session holds the course and the assignment is available in it). The commenter is skipped too.
    • On the API path, the course and session are taken from the submission's own resource link, not from the request's cid.
    • Teacher comments still only go to the learner, and only when "send e-mail" is ticked, as before.
  • Master switch is kept. email_to_teachers_on_new_work_feedback still decides whether anyone is told: when it is not 1, nobody is e-mailed, whatever they follow. This reads the setting exactly the way the legacy 1 != api_get_course_setting(...) check did.

  • The creator follows automatically on every creation path:

    • legacy addDir() (work.php)
    • the API POST /api/c_student_publications (CStudentPublicationPostStateProcessor, top-level folders only)
    • the MCP McpCourseAssignmentCreator

    The creator can unfollow like anyone else.

  • Endpoints (in StudentPublicationController, under /assignments):

    • GET /assignments/{id}/follow: returns {following: bool}
    • POST /assignments/{id}/follow: follow
    • DELETE /assignments/{id}/follow: unfollow

    Access:

    • Course teachers, the assignment's creator and admins pass the EDIT vote on the assignment's resource node (ResourceNodeVoter).
    • A session coach passes for the session given by sid only: they must be the course coach of the request's course (cid) in that session, or its general coach; the session must hold the course; and the assignment must be available in that session (a base-course link, or a link to that very session). This check lives in the small AssignmentSessionCoachAccess service, which reloads the course and session by id and uses the existing Session::hasCourse(), hasCourseCoachInCourse() and hasUserAsGeneralCoach() helpers. ResourceNodeVoter itself is unchanged: it still refuses coaches the right to edit base-course assignments.
    • Learners, teachers of other courses and coaches of other sessions get 403. Only a top-level assignment can be followed: a submission id returns 404. The user always comes from UserHelper::getCurrent() and is never read from the client.
    • POST and DELETE are covered by the existing CsrfProtectionListener (Origin / Sec-Fetch checks).
  • UI

    • Vue AssignmentDetail.vue (teacher toolbar, also shown to session coaches): a Follow / Following toggle (bell-off-outline / bell). It stays hidden until the state is loaded and is never shown to learners.
    • Legacy work_list_all.php (still linked from LP, view.php and others): an ActionIcon::EMAIL_OFF / EMAIL_ON toggle, the same icons the wiki uses for "Notify me". Clicking it calls the same POST/DELETE endpoint, so no new legacy handler or token was added.
    • New strings: "Following" and "Get an e-mail when a learner comments on a submission of this assignment", added to messages.pot, messages.en_US.po and en_US.json. "Follow" already existed in the catalogs and was added to en_US.json.

Release note

Assignments: teachers now choose which assignments e-mail them about learners' comments, with the new Follow button. After the upgrade, only the creator of each existing assignment follows it: co-teachers must click Follow on the existing assignments they want to keep receiving learner comment e-mails for.

Migration note (existing assignments)

V310/Version20261020120000 creates the table. It also makes the creator of each existing assignment (the user_id of every top-level folder row whose user still exists) a follower, so that behaviour does not silently change to "no e-mails" after the upgrade.

Trade-off: before this PR every course teacher was told. After the upgrade only the creator is, and co-teachers must click Follow on the assignments they care about. That is what the issue asks for (no more unwanted e-mails), but co-teachers who relied on the old e-mails will stop getting them until they opt in. The alternative was to make every current course teacher a follower of every existing assignment. That keeps the old behaviour exactly, but it also keeps the unwanted e-mails the issue complains about. down() drops the table.

How to test

  1. Run php bin/console doctrine:migrations:migrate. Check that c_student_publication_follow exists and has one row per existing assignment creator.
  2. As teacher A, create an assignment (Vue screen). Open it: the toolbar shows Following.
  3. As teacher B (another teacher of the same course), open it: it shows Follow. Click it and it becomes Following. Reload and it stays.
  4. As a learner, submit a file to the assignment, then add a comment to the submission (from the Vue screen or from main/work/view.php). The teachers showing Following receive the "There's a new feedback in work" message/e-mail, and the others do not.
  5. Set Course settings › "E-mail to teachers on new user's student publication feedback" to No and comment again: nobody is e-mailed.
  6. Add the course to a session with a course coach. As that coach, open the assignment inside the session (?cid={cid}&sid={sid}): the toolbar shows Follow, and following works. A learner of that session commenting on their submission e-mails the coach. A coach of another session gets 403 when calling POST /assignments/{id}/follow?cid={cid}&sid={sid} for that session, and is not e-mailed about comments made in it.
  7. As a learner, call POST /assignments/{id}/follow?cid={cid}: you get 403. A teacher of another course gets 403 too.

Automated:

php bin/phpunit tests/CoreBundle/Service/Assignment/AssignmentFeedbackNotifierTest.php
php bin/phpunit tests/CoreBundle/Controller/StudentPublicationFollowTest.php
npx playwright test --config=tests/playwright/playwright.config.ts tests/playwright/.features-gen/features/toolWorkFollow.feature.spec.js tests/playwright/.features-gen/features/toolWork.feature.spec.js

Documentation

A draft for the docs repository is attached separately (3.x/en/teacher-guide/assessing-learners/assignments.md, new section "Following an Assignment"). It is not part of this PR's code.

@ywarnier
ywarnier merged commit 5aadaf9 into chamilo:master Oct 20, 2026
3 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Student publications tool 1.10.x: Feedback on work emails are sent to all teachers of a course

2 participants