From 7f4657def4678ae0aec92a62af478a7903823eb4 Mon Sep 17 00:00:00 2001 From: Ahmad Altaher Alfayad Date: Fri, 10 May 2024 12:59:34 -0400 Subject: [PATCH] add replacement functionality for pages and modules --- src/Lms/Canvas/CanvasApi.php | 99 +++++++++++++++++++++++++++++++++++- src/Lms/Canvas/CanvasLms.php | 45 +++++++++++++++- 2 files changed, 142 insertions(+), 2 deletions(-) diff --git a/src/Lms/Canvas/CanvasApi.php b/src/Lms/Canvas/CanvasApi.php index 7415b049..cb2487b9 100644 --- a/src/Lms/Canvas/CanvasApi.php +++ b/src/Lms/Canvas/CanvasApi.php @@ -106,7 +106,7 @@ public function apiPost($url, $options, $sendAuthorized = true) } // Posts a file to Canvas - public function apiFilePost(string $url, array $options, string $filepath, string $newFileName): LmsResponse + public function apiFilePost(string $url, array $options, string $filepath, string $newFileName, $moduleInstances = null, $courseId = null, $replacePages = null) : LmsResponse { $fileResponse = $this->apiGet($url); $file = $fileResponse->getContent(); @@ -135,6 +135,59 @@ public function apiFilePost(string $url, array $options, string $filepath, strin 'body' => $formData->bodyToIterable(), ], false); + $fileResponseContent = $fileResponse->getContent(); + + if($moduleInstances) { + foreach ($moduleInstances as $moduleInstance) { + $response = $this->apiPost("courses/{$courseId}/modules/{$moduleInstance}/items", [ + 'json' => [ + 'module_item' => [ + 'title' => $newFileName, + 'type' => 'File', + 'content_id' => $fileResponseContent['id'], + ], + ], + ]); + + } + } + + if($replacePages) { + foreach ($replacePages as $page) { + $dom = new \DOMDocument(); + $dom->loadHTML($page['body']); + $anchors = $dom->getElementsByTagName('a'); + foreach ($anchors as $anchor) { + preg_match('/files\/(\d+)/', $anchor->getAttribute('href'), $matches); + if (isset($matches[1]) && $matches[1] == $file['id']) { + $anchor->setAttribute('href', $fileResponseContent['url']); + $anchor->setAttribute('title', $newFileName); + $anchor->nodeValue = $newFileName; + } + $page['body'] = $dom->saveHTML(); + $response = $this->apiPut("courses/{$courseId}/pages/{$page['page_id']}", [ + 'json' => [ + 'wiki_page' => [ + 'title' => $page['title'], + 'body' => $page['body'], + 'editing_roles' => $page['editing_roles'], + 'published' => $page['published'], + 'front_page' => $page['front_page'], + 'hide_from_students' => $page['hide_from_students'], + 'notify_of_update' => $page['notify_of_update'], + 'attachments' => [ + [ + 'url' => $fileResponseContent['url'], + 'filename' => $newFileName, + ], + ], + ], + ], + ]); + } + } + } + return $fileResponse; } @@ -189,4 +242,48 @@ public function apiDelete($url) { } + public function listModules($courseId) + { + $url = "courses/{$courseId}/modules"; + $response = $this->apiGet($url); + return $response->getContent(); + } + + public function listModuleItems($courseId, $moduleId) + { + $url = "courses/{$courseId}/modules/{$moduleId}/items"; + $response = $this->apiGet($url); + return $response->getContent(); + } + + public function deleteModuleItem($courseId, $moduleId, $itemId) + { + $url = "courses/{$courseId}/modules/{$moduleId}/items/{$itemId}"; + $response = $this->apiDelete($url); + return $response->getContent(); + } + + public function listPages($courseId) + { + $url = "courses/{$courseId}/pages"; + $response = $this->apiGet($url . '?include[]=body'); + + $responseWithPageBody = []; + + foreach ($response->getContent() as $content) { + $page = $this->showPage($courseId, $content['page_id']); + $content['body'] = $page['body']; + $responseWithPageBody[] = $content; + } + + return $responseWithPageBody; + } + + public function showPage($courseId, $pageId) + { + $url = "courses/{$courseId}/pages/{$pageId}"; + $response = $this->apiGet($url . '?include[]=body'); + return $response->getContent(); + } + } diff --git a/src/Lms/Canvas/CanvasLms.php b/src/Lms/Canvas/CanvasLms.php index 341d41df..18332643 100644 --- a/src/Lms/Canvas/CanvasLms.php +++ b/src/Lms/Canvas/CanvasLms.php @@ -376,13 +376,44 @@ public function postFileItem(FileItem $file, string $newFileName) $apiDomain = $this->getApiDomain($user); $apiToken = $this->getApiToken($user); $canvasApi = new CanvasApi($apiDomain, $apiToken); + $modules = $canvasApi->listModules($file->getCourse()->getLmsCourseId()); + $pages = $canvasApi->listPages($file->getCourse()->getLmsCourseId()); + $refillModules = []; + $changePages = []; + + // Delete any existing module items with the same file name + foreach ($modules as $module) { + $moduleItems = $canvasApi->listModuleItems($file->getCourse()->getLmsCourseId(), $module['id']); + $instances = $this->findFileInModuleItems($moduleItems, $file->getLmsFileId()); + if (!empty($instances)) { + foreach ($instances as $instance) { + $canvasApi->deleteModuleItem($file->getCourse()->getLmsCourseId(), $module['id'], $instance['id']); + } + $refillModules[] = $module['id']; + } + } + + // Find all pages that contain this file in their HTML + foreach ($pages as $page) { + $dom = new \DOMDocument(); + $dom->loadHTML($page['body']); + $anchors = $dom->getElementsByTagName('a'); + foreach ($anchors as $anchor) { + preg_match('/files\/(\d+)/', $anchor->getAttribute('href'), $matches); + if(isset($matches[1]) && $matches[1] == $file->getLmsFileId()) { + $changePages[] = $page; + break; + } + } + } + $url = "courses/{$file->getCourse()->getLmsCourseId()}/files/{$file->getLmsFileId()}"; $filepath = $this->util->getTempPath() . '/file.' . $file->getId(); $options = [ 'postUrl' => "courses/{$file->getCourse()->getLmsCourseId()}/files" ]; - $fileResponse = $canvasApi->apiFilePost($url, $options, $filepath, $newFileName); + $fileResponse = $canvasApi->apiFilePost($url, $options, $filepath, $newFileName, $refillModules, $file->getCourse()->getLmsCourseId(), $changePages); $fileObj = $fileResponse->getContent(); if (isset($fileObj['id'])) { @@ -393,6 +424,18 @@ public function postFileItem(FileItem $file, string $newFileName) return $fileResponse; } + public function findFileInModuleItems($moduleItems, string $fileId) + { + $instances = []; + foreach ($moduleItems as $item) { + if ($item['content_id'] == $fileId) { + $instances[] = $item; + } + } + + return $instances; + } + public function getCourseUrl(Course $course, User $user) { $domain = $this->getApiDomain($user);