{"id":28156776,"url":"https://github.com/suparnad/recently_viewed_courses","last_synced_at":"2026-04-28T18:03:14.119Z","repository":{"id":293347306,"uuid":"983746359","full_name":"suparnad/recently_viewed_courses","owner":"suparnad","description":"A custom Drupal 11 module that displays a cacheable list of popular courses and a session-based recently viewed courses block using lazy builders, services, and render arrays.","archived":false,"fork":false,"pushed_at":"2025-05-14T21:26:05.000Z","size":11,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-14T22:26:56.866Z","etag":null,"topics":["custom-module","drupal","drupal-11"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/suparnad.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-05-14T21:14:38.000Z","updated_at":"2025-05-14T21:28:00.000Z","dependencies_parsed_at":"2025-05-14T22:37:44.019Z","dependency_job_id":null,"html_url":"https://github.com/suparnad/recently_viewed_courses","commit_stats":null,"previous_names":["suparnad/recently_viewed_courses"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/suparnad/recently_viewed_courses","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suparnad%2Frecently_viewed_courses","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suparnad%2Frecently_viewed_courses/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suparnad%2Frecently_viewed_courses/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suparnad%2Frecently_viewed_courses/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/suparnad","download_url":"https://codeload.github.com/suparnad/recently_viewed_courses/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suparnad%2Frecently_viewed_courses/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32392304,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T14:34:11.604Z","status":"ssl_error","status_checked_at":"2026-04-28T14:32:37.009Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["custom-module","drupal","drupal-11"],"created_at":"2025-05-15T08:15:05.579Z","updated_at":"2026-04-28T18:03:14.093Z","avatar_url":"https://github.com/suparnad.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Recently Viewed Courses\n\nSample Problem Solving Task: “Recently Viewed Courses Page”\n\n## Scenario:\n\nThe University wants a page on the website that shows:\n\n- A cacheable block of curated \"Popular Courses\".\n\n- A non-cacheable block of \"Recently Viewed Courses\" (tracked per user session).\n\n- Clean separation of frontend logic using Twig templates and CSS classes.\n\n- Accessibility in markup and semantic HTML.\n\n---\n\n## Task Requirements:\n\n1. Create a custom module called recently_viewed_courses.\n\n2. On visiting /courses/recently-viewed, the page should:\n\n  - Display Popular Courses (static content for now).\n\n  - Display Recently Viewed Courses stored in user session.\n\n3. Use render arrays and #lazy_builder for the non-cacheable part.\n\n4. Write a service to handle session storage for recently viewed courses.\n\n5. Ensure the page is accessible and responsive.\n\n\n---\n\n## Features\n\n- Adds a custom page at `/courses/recently-viewed`.\n- Displays:\n  - **Popular Courses** (cacheable content).\n  - **Recently Viewed Courses** (user session-based, non-cacheable).\n- Uses:\n  - Render arrays and lazy builders (can be switched to direct block rendering).\n  - Twig template for clean and accessible frontend output.\n  - A custom service for session-based storage of recently viewed items.\n- Accessibility support with ARIA labels and semantic HTML.\n\n---\n\n## Installation\n\n1. Clone the module or copy it into the `modules/custom/` directory of your Drupal project.\n\n  ```bash\n  cd web/modules/custom\n  git clone https://github.com/your-repo/recently_viewed_courses.git\n  ```\n\n2. Enable the module using Drush or the admin UI.\n\n  ```bash\n  drush en recently_viewed_courses\n  ```\n\n3. Visit /courses/recently-viewed to test the feature.\n\n---\n\n## How It Works\n\n1. CoursePageController.php\n\n    Defines the page route and render array.\n    \n    Uses #theme =\u003e 'course_page' to load the Twig template.\n    \n    Includes #lazy_builder to call a trusted service method to render the dynamic block.\n\n2. RecentlyViewedBlock.php\n\n    A custom block plugin that fetches recently viewed course names from the session using a service (CourseTracker).\n    \n    Returned block content is never cached (#cache =\u003e ['max-age' =\u003e 0]).\n\n3. CourseTracker.php\n\n    A custom service that adds and retrieves course names from PHP session.\n    \n    Limits the session history to 5 unique entries.\n\n4. RecentlyViewedLazyBuilder.php\n\n    A custom lazy builder service that securely loads and returns the RecentlyViewedBlock render array.\n    \n    Implements TrustedCallbackInterface to allow render() to be safely used with #lazy_builder.\n\n---\n\n## Test\n\nNow visit:\n  https://my-first-drupal10-app.ddev.site:8443/course/view/psychology\n  \n  https://my-first-drupal10-app.ddev.site:8443/course/view/ai\n\nThen go back to:\nhttps://my-first-drupal10-app.ddev.site:8443/courses/recently-viewed\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsuparnad%2Frecently_viewed_courses","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsuparnad%2Frecently_viewed_courses","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsuparnad%2Frecently_viewed_courses/lists"}