first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
@@ -0,0 +1,120 @@
<?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 repository_googledocs;
/**
* Base class for presenting the googledocs repository contents.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class googledocs_content {
/** @var rest The rest API object. */
protected $service;
/** @var string The current path. */
protected $path;
/** @var bool Whether sorting should be applied to the fetched content. */
protected $sortcontent;
/**
* Constructor.
*
* @param rest $service The rest API object
* @param string $path The current path
* @param bool $sortcontent Whether sorting should be applied to the content
*/
public function __construct(rest $service, string $path, bool $sortcontent = true) {
$this->service = $service;
$this->path = $path;
$this->sortcontent = $sortcontent;
}
/**
* Generate and return an array containing all repository node (files and folders) arrays for the existing content
* based on the path or search query.
*
* @param string $query The search query
* @param callable $isaccepted The callback function which determines whether a given file should be displayed
* or filtered based on the existing file restrictions
* @return array The array containing the repository content node arrays
*/
public function get_content_nodes(string $query, callable $isaccepted): array {
$files = [];
$folders = [];
foreach ($this->get_contents($query) as $gdcontent) {
$node = helper::get_node($gdcontent, $this->path);
// Create the repository node array.
$nodearray = $node->create_node_array();
// If the repository node array was successfully generated and the type of the content is accepted,
// add it to the repository content nodes array.
if ($nodearray && $isaccepted($nodearray)) {
// Group the content nodes by type (files and folders). Generate unique array keys for each content node
// which will be later used by the sorting function. Note: Using the item id along with the name as key
// of the array because Google Drive allows files and folders with identical names.
if (isset($nodearray['source'])) { // If the content node has a source attribute, it is a file node.
$files["{$nodearray['title']}{$nodearray['id']}"] = $nodearray;
} else {
$folders["{$nodearray['title']}{$nodearray['id']}"] = $nodearray;
}
}
}
// If sorting is required, order the results alphabetically by their array keys.
if ($this->sortcontent) {
\core_collator::ksort($files, \core_collator::SORT_STRING);
\core_collator::ksort($folders, \core_collator::SORT_STRING);
}
return array_merge(array_values($folders), array_values($files));
}
/**
* Build the navigation (breadcrumb) from a given path.
*
* @return array Array containing name and path of each navigation node
*/
public function get_navigation(): array {
$nav = [];
$navtrail = '';
$pathnodes = explode('/', $this->path);
foreach ($pathnodes as $node) {
list($id, $name) = helper::explode_node_path($node);
$name = empty($name) ? $id : $name;
$nav[] = [
'name' => $name,
'path' => helper::build_node_path($id, $name, $navtrail),
];
$tmp = end($nav);
$navtrail = $tmp['path'];
}
return $nav;
}
/**
* Returns all relevant contents (files and folders) based on the given path or search query.
*
* @param string $query The search query
* @return array The array containing the contents
*/
abstract protected function get_contents(string $query): array;
}
@@ -0,0 +1,67 @@
<?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 repository_googledocs;
/**
* Utility class for displaying google drive content that matched a given search criteria.
*
* This class is responsible for generating the content that is returned based on a given search query.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class googledocs_content_search extends googledocs_content {
/**
* Returns all relevant contents based on the given path and/or search query.
*
* The method fetches all content (files) through an API call that matches a given search criteria.
*
* @param string $query The search query
* @return array The array containing the contents
*/
protected function get_contents(string $query): array {
$searchterm = str_replace("'", "\'", $query);
// Define the parameters required by the API call.
// Query all contents which name contains $searchterm and have not been trashed.
$q = "fullText contains '{$searchterm}' AND trashed = false";
// The file fields that should be returned in the response.
$fields = "files(id,name,mimeType,webContentLink,webViewLink,fileExtension,modifiedTime,size,iconLink)";
$params = [
'q' => $q,
'fields' => $fields,
'spaces' => 'drive',
];
// If shared drives exist, include the additional required parameters in order to extend the content search
// into the shared drives area as well.
$response = helper::request($this->service, 'shared_drives_list', []);
if (!empty($response->drives)) {
$params['supportsAllDrives'] = 'true';
$params['includeItemsFromAllDrives'] = 'true';
$params['corpora'] = 'allDrives';
}
// Request the content through the API call.
$response = helper::request($this->service, 'list', $params);
return $response->files ?? [];
}
}
+143
View File
@@ -0,0 +1,143 @@
<?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 repository_googledocs;
use repository_googledocs\local\browser\googledocs_root_content;
use repository_googledocs\local\browser\googledocs_shared_drives_content;
use repository_googledocs\local\browser\googledocs_drive_content;
use repository_googledocs\local\node\node;
use repository_googledocs\local\node\file_node;
use repository_googledocs\local\node\folder_node;
/**
* Helper class for the googledocs repository.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class helper {
/**
* Generates a safe path to a node.
*
* Typically, a node will be id|name of the node.
*
* @param string $id The ID of the node
* @param string $name The name of the node, will be URL encoded
* @param string $root The path to append the node on (must be a result of this function)
* @return string The path to the node
*/
public static function build_node_path(string $id, string $name = '', string $root = ''): string {
$path = $id;
if (!empty($name)) {
$path .= '|' . urlencode($name);
}
if (!empty($root)) {
$path = trim($root, '/') . '/' . $path;
}
return $path;
}
/**
* Returns information about a node in a path.
*
* @param string $node The node string to extract information from
* @return array The array containing the information about the node
* @see self::build_node_path()
*/
public static function explode_node_path(string $node): array {
if (strpos($node, '|') !== false) {
list($id, $name) = explode('|', $node, 2);
$name = urldecode($name);
} else {
$id = $node;
$name = '';
}
$id = urldecode($id);
return [
0 => $id,
1 => $name,
'id' => $id,
'name' => $name,
];
}
/**
* Returns the relevant googledocs content browser class based on the given path.
*
* @param rest $service The rest API object
* @param string $path The current path
* @return googledocs_content The googledocs repository content browser
*/
public static function get_browser(rest $service, string $path): googledocs_content {
$pathnodes = explode('/', $path);
$currentnode = self::explode_node_path(array_pop($pathnodes));
// Return the relevant content browser class based on the ID of the current path node.
switch ($currentnode['id']) {
case \repository_googledocs::REPOSITORY_ROOT_ID:
return new googledocs_root_content($service, $path, false);
case \repository_googledocs::SHARED_DRIVES_ROOT_ID:
return new googledocs_shared_drives_content($service, $path);
default:
return new googledocs_drive_content($service, $path);
}
}
/**
* Returns the relevant repository content node class based on the Google Drive file's mimetype.
*
* @param \stdClass $gdcontent The Google Drive content (file/folder) object
* @param string $path The current path
* @return node The content node object
*/
public static function get_node(\stdClass $gdcontent, string $path): node {
// Return the relevant content browser class based on the ID of the current path node.
switch ($gdcontent->mimeType) {
case 'application/vnd.google-apps.folder':
return new folder_node($gdcontent, $path);
default:
return new file_node($gdcontent);
}
}
/**
* Wrapper function to perform an API call and also catch and handle potential exceptions.
*
* @param rest $service The rest API object
* @param string $api The name of the API call
* @param array $params The parameters required by the API call
* @return \stdClass The response object
* @throws \repository_exception
*/
public static function request(rest $service, string $api, array $params): ?\stdClass {
try {
// Retrieving files and folders.
$response = $service->call($api, $params);
} catch (\Exception $e) {
if ($e->getCode() == 403 && strpos($e->getMessage(), 'Access Not Configured') !== false) {
// This is raised when the service Drive API has not been enabled on Google APIs control panel.
throw new \repository_exception('servicenotenabled', 'repository_googledocs');
}
throw $e;
}
return $response;
}
}
@@ -0,0 +1,74 @@
<?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 repository_googledocs\local\browser;
use repository_googledocs\googledocs_content;
use repository_googledocs\helper;
/**
* Utility class for browsing content from or within a specified google drive.
*
* This class is responsible for generating the content that would be displayed for a specified drive such as
* 'my drive' or any existing shared drive. It also supports generating data for paths which are located
* within a given drive.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class googledocs_drive_content extends googledocs_content {
/**
* Returns all relevant contents based on the given path or search query.
*
* The method fetches all existing content (files and folders) located in a specific folder under a given drive
* through an API call.
*
* @param string $query The search query
* @return array The array containing the contents
*/
protected function get_contents(string $query): array {
$id = str_replace("'", "\'", $query);
// Define the parameters required by the API call.
// Query all files and folders which have not been trashed and located directly in the folder whose ID is $id.
$q = "'{$id}' in parents AND trashed = false";
// The file fields that should be returned in the response.
$fields = 'files(id,name,mimeType,webContentLink,webViewLink,fileExtension,modifiedTime,size,iconLink)';
$params = [
'q' => $q,
'fields' => $fields,
'spaces' => 'drive',
];
// Check whether there are any shared drives.
$response = helper::request($this->service, 'shared_drives_list', []);
if (!empty($response->drives)) {
// To be able to include content from shared drives, we need to enable 'supportsAllDrives' and
// 'includeItemsFromAllDrives'. The Google Drive API requires explicit request for inclusion of content from
// shared drives and also a confirmation that the application is designed to handle files on shared drives.
$params['supportsAllDrives'] = 'true';
$params['includeItemsFromAllDrives'] = 'true';
}
// Request the content through the API call.
$response = helper::request($this->service, 'list', $params);
return $response->files ?? [];
}
}
@@ -0,0 +1,67 @@
<?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 repository_googledocs\local\browser;
use repository_googledocs\googledocs_content;
use repository_googledocs\helper;
/**
* Utility class for browsing the content within the googledocs repository root.
*
* This class is responsible for generating the content that would be displayed in the googledocs repository root.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class googledocs_root_content extends googledocs_content {
/**
* Returns all relevant contents based on the given path or search query.
*
* The method predefines the content which will be displayed in the repository root level. Currently,
* only the folders representing 'My drives' and 'Shared drives' will be displayed in the root level.
*
* @param string $query The search query
* @return array The array containing the contents
*/
protected function get_contents(string $query): array {
// Add 'My drive' folder into the displayed contents.
$contents = [
(object)[
'id' => \repository_googledocs::MY_DRIVE_ROOT_ID,
'name' => get_string('mydrive', 'repository_googledocs'),
'mimeType' => 'application/vnd.google-apps.folder',
'modifiedTime' => '',
],
];
// If shared drives exists, include 'Shared drives' folder to the displayed contents.
$response = helper::request($this->service, 'shared_drives_list', []);
if (!empty($response->drives)) {
$contents[] = (object)[
'id' => \repository_googledocs::SHARED_DRIVES_ROOT_ID,
'name' => get_string('shareddrives', 'repository_googledocs'),
'mimeType' => 'application/vnd.google-apps.folder',
'modifiedTime' => '',
];
}
return $contents;
}
}
@@ -0,0 +1,60 @@
<?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 repository_googledocs\local\browser;
use repository_googledocs\googledocs_content;
use repository_googledocs\helper;
/**
* Utility class for browsing the content within the googledocs repository shared drives root.
*
* This class is responsible for generating the content that would be displayed in the googledocs repository
* shared drives root.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class googledocs_shared_drives_content extends googledocs_content {
/**
* Returns all relevant contents based on the given path or search query.
*
* The method generates the content which will be displayed in the repository shared drives root level.
* All existing shared drives will be fetched through an API call and presented as folders.
*
* @param string $query The search query
* @return array The array containing the contents
*/
protected function get_contents(string $query): array {
// Make an API request to get all existing shared drives.
$response = helper::request($this->service, 'shared_drives_list', []);
// If shared drives exist, create folder for each shared drive.
if ($shareddrives = $response->drives) {
return array_map(function($shareddrive) {
return (object)[
'id' => $shareddrive->id,
'name' => $shareddrive->name,
'mimeType' => 'application/vnd.google-apps.folder',
'modifiedTime' => '',
];
}, $shareddrives);
}
return [];
}
}
@@ -0,0 +1,210 @@
<?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 repository_googledocs\local\node;
/**
* Class used to represent a file node in the googledocs repository.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class file_node implements node {
/** @var string The ID of the file node. */
private $id;
/** @var string|null The title of the file node. */
private $title;
/** @var string The name of the file. */
private $name;
/** @var string|null The file's export format. */
private $exportformat;
/** @var string The external link to the file. */
private $link;
/** @var string The timestamp representing the last modified date. */
private $modified;
/** @var string|null The size of the file. */
private $size;
/** @var string The thumbnail of the file. */
private $thumbnail;
/** @var string|null The type of the Google Doc file (document, presentation, etc.), null if it is a regular file. */
private $googledoctype;
/**
* Constructor.
*
* @param \stdClass $gdfile The Google Drive file object
*/
public function __construct(\stdClass $gdfile) {
$this->id = $gdfile->id;
$this->title = $this->generate_file_title($gdfile);
$this->name = $gdfile->name;
$this->exportformat = $this->generate_file_export_format($gdfile);
$this->link = $this->generate_file_link($gdfile);
$this->modified = ($gdfile->modifiedTime) ? strtotime($gdfile->modifiedTime) : '';
$this->size = !empty($gdfile->size) ? $gdfile->size : null;
// Use iconLink as a file thumbnail if set, otherwise use the default icon depending on the file type.
// Note: The Google Drive API can return a link to a preview thumbnail of the file (via thumbnailLink).
// However, in many cases the Google Drive files are not public and an authorized request is required
// to get the thumbnail which we currently do not support. Therefore, to avoid displaying broken
// thumbnail images in the repository, the icon of the Google Drive file is being used as a thumbnail
// instead as it does not require an authorized request.
// Currently, the returned file icon link points to the 16px version of the icon by default which would result
// in displaying 16px file thumbnails in the repository. To avoid this, the link can be slightly modified in
// order to get a larger version of the icon as there isn't an option to request this through the API call.
$this->thumbnail = !empty($gdfile->iconLink) ? str_replace('/16/', '/64/', $gdfile->iconLink) : '';
$this->googledoctype = !isset($gdfile->fileExtension) ?
str_replace('application/vnd.google-apps.', '', $gdfile->mimeType) : null;
}
/**
* Create a repository file array.
*
* This method returns an array which structure is compatible to represent a file node in the repository.
*
* @return array|null The node array or null if the node could not be created
*/
public function create_node_array(): ?array {
// Cannot create the file node if the file title was not generated or the export format.
// This means that the current file type is invalid or unknown.
if (!$this->title || !$this->exportformat) {
return null;
}
return [
'id' => $this->id,
'title' => $this->title,
'source' => json_encode(
[
'id' => $this->id,
'name' => $this->name,
'link' => $this->link,
'exportformat' => $this->exportformat,
'googledoctype' => $this->googledoctype,
]
),
'date' => $this->modified,
'size' => $this->size,
'thumbnail' => $this->thumbnail,
'thumbnail_height' => 64,
'thumbnail_width' => 64,
];
}
/**
* Generates and returns the title for the file node depending on the type of the Google drive file.
*
* @param \stdClass $gdfile The Google Drive file object
* @return string The file title
*/
private function generate_file_title(\stdClass $gdfile): ?string {
// Determine the file type through the file extension.
if (isset($gdfile->fileExtension)) { // The file is a regular file.
return $gdfile->name;
} else { // The file is probably a Google Doc file.
// We need to generate the name by appending the proper google doc extension.
$type = str_replace('application/vnd.google-apps.', '', $gdfile->mimeType);
if ($type === 'document') {
return "{$gdfile->name}.gdoc";
}
if ($type === 'presentation') {
return "{$gdfile->name}.gslides";
}
if ($type === 'spreadsheet') {
return "{$gdfile->name}.gsheet";
}
if ($type === 'drawing') {
$config = get_config('googledocs');
$ext = $config->drawingformat;
return "{$gdfile->name}.{$ext}";
}
}
return null;
}
/**
* Generates and returns the file export format depending on the type of the Google drive file.
*
* @param \stdClass $gdfile The Google Drive file object
* @return string The file export format
*/
private function generate_file_export_format(\stdClass $gdfile): ?string {
// Determine the file type through the file extension.
if (isset($gdfile->fileExtension)) { // The file is a regular file.
// The file has an extension, therefore we can download it.
return 'download';
} else {
// The file is probably a Google Doc file, we get the corresponding export link.
$type = str_replace('application/vnd.google-apps.', '', $gdfile->mimeType);
$types = get_mimetypes_array();
$config = get_config('googledocs');
if ($type === 'document' && !empty($config->documentformat)) {
$ext = $config->documentformat;
if ($ext === 'rtf') {
// Moodle user 'text/rtf' as the MIME type for RTF files.
// Google uses 'application/rtf' for the same type of file.
// See https://developers.google.com/drive/v3/web/manage-downloads.
return 'application/rtf';
} else {
return $types[$ext]['type'];
}
}
if ($type === 'presentation' && !empty($config->presentationformat)) {
$ext = $config->presentationformat;
return $types[$ext]['type'];
}
if ($type === 'spreadsheet' && !empty($config->spreadsheetformat)) {
$ext = $config->spreadsheetformat;
return $types[$ext]['type'];
}
if ($type === 'drawing' && !empty($config->drawingformat)) {
$ext = $config->drawingformat;
return $types[$ext]['type'];
}
}
return null;
}
/**
* Generates and returns the external link to the file.
*
* @param \stdClass $gdfile The Google Drive file object
* @return string The link to the file
*/
private function generate_file_link(\stdClass $gdfile): string {
// If the google drive file has webViewLink set, use it as an external link.
$link = !empty($gdfile->webViewLink) ? $gdfile->webViewLink : '';
// Otherwise, use webContentLink if set or leave the external link empty.
if (empty($link) && !empty($gdfile->webContentLink)) {
$link = $gdfile->webContentLink;
}
return $link;
}
}
@@ -0,0 +1,76 @@
<?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 repository_googledocs\local\node;
use repository_googledocs\helper;
/**
* Class used to represent a folder node in the googledocs repository.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class folder_node implements node {
/** @var string The ID of the folder node. */
private $id;
/** @var string The title of the folder node. */
private $title;
/** @var bool The timestamp representing the last modified date. */
private $modified;
/** @var string The path of the folder node. */
private $path;
/**
* Constructor.
*
* @param \stdClass $gdfolder The Google Drive folder object
* @param string $path The path of the folder node
*/
public function __construct(\stdClass $gdfolder, string $path) {
$this->id = $gdfolder->id;
$this->title = $gdfolder->name;
$this->modified = $gdfolder->modifiedTime ? strtotime($gdfolder->modifiedTime) : '';
$this->path = $path;
}
/**
* Create a repository folder array.
*
* This method returns an array which structure is compatible to represent a folder node in the repository.
*
* @return array|null The node array or null if the node could not be created
*/
public function create_node_array(): ?array {
global $OUTPUT;
return [
'id' => $this->id,
'title' => $this->title,
'path' => helper::build_node_path($this->id, $this->title, $this->path),
'date' => $this->modified,
'thumbnail' => $OUTPUT->image_url(file_folder_icon())->out(false),
'thumbnail_height' => 64,
'thumbnail_width' => 64,
'children' => [],
];
}
}
@@ -0,0 +1,37 @@
<?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 repository_googledocs\local\node;
/**
* The googledocs repository content node interface.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
interface node {
/**
* Create a repository node array.
*
* This method returns an array which structure is compatible to represent a content node (file/folder)
* in the repository.
*
* @return array|null The node array or null if the node could not be created
*/
public function create_node_array(): ?array;
}
@@ -0,0 +1,116 @@
<?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/>.
/**
* Privacy Subsystem implementation for repository_googledocs.
*
* @package repository_googledocs
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace repository_googledocs\privacy;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\approved_userlist;
use core_privacy\local\request\context;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\userlist;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for repository_googledocs implementing metadata and plugin providers.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
\core_privacy\local\metadata\provider,
\core_privacy\local\request\core_userlist_provider,
\core_privacy\local\request\plugin\provider {
/**
* Returns meta data about this system.
*
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection): collection {
$collection->add_external_location_link(
'drive.google.com',
[
'email' => 'privacy:metadata:repository_googledocs:email',
'searchtext' => 'privacy:metadata:repository_googledocs:searchtext'
],
'privacy:metadata:repository_googledocs'
);
return $collection;
}
/**
* Get the list of contexts that contain user information for the specified user.
*
* @param int $userid The user to search.
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
*/
public static function get_contexts_for_userid(int $userid): contextlist {
return new contextlist();
}
/**
* Get the list of users who have data within a context.
*
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
*/
public static function get_users_in_context(userlist $userlist) {
}
/**
* Export all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts to export information for.
*/
public static function export_user_data(approved_contextlist $contextlist) {
}
/**
* Delete all data for all users in the specified context.
*
* @param context $context The specific context to delete data for.
*/
public static function delete_data_for_all_users_in_context(\context $context) {
}
/**
* Delete all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
}
/**
* Delete multiple users within a single context.
*
* @param approved_userlist $userlist The approved context and user information to delete information for.
*/
public static function delete_data_for_users(approved_userlist $userlist) {
}
}
+142
View File
@@ -0,0 +1,142 @@
<?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/>.
/**
* Google Drive Rest API.
*
* @package repository_googledocs
* @copyright 2017 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace repository_googledocs;
defined('MOODLE_INTERNAL') || die();
/**
* Google Drive Rest API.
*
* @copyright 2017 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class rest extends \core\oauth2\rest {
/**
* Define the functions of the rest API.
*
* @return array Example:
* [ 'listFiles' => [ 'method' => 'get', 'endpoint' => 'http://...', 'args' => [ 'folder' => PARAM_STRING ] ] ]
*/
public function get_api_functions() {
return [
'list' => [
'endpoint' => 'https://www.googleapis.com/drive/v3/files',
'method' => 'get',
'args' => [
'corpus' => PARAM_RAW,
'orderBy' => PARAM_RAW,
'fields' => PARAM_RAW,
'pageSize' => PARAM_INT,
'pageToken' => PARAM_RAW,
'q' => PARAM_RAW,
'spaces' => PARAM_RAW,
'supportsAllDrives' => PARAM_RAW,
'includeItemsFromAllDrives' => PARAM_RAW,
'corpora' => PARAM_RAW
],
'response' => 'json'
],
'get' => [
'endpoint' => 'https://www.googleapis.com/drive/v3/files/{fileid}',
'method' => 'get',
'args' => [
'fields' => PARAM_RAW,
'fileid' => PARAM_RAW
],
'response' => 'json'
],
'copy' => [
'endpoint' => 'https://www.googleapis.com/drive/v3/files/{fileid}/copy',
'method' => 'post',
'args' => [
'fields' => PARAM_RAW,
'fileid' => PARAM_RAW
],
'response' => 'json'
],
'delete' => [
'endpoint' => 'https://www.googleapis.com/drive/v3/files/{fileid}',
'method' => 'delete',
'args' => [
'fileid' => PARAM_RAW
],
'response' => 'json'
],
'create' => [
'endpoint' => 'https://www.googleapis.com/drive/v3/files',
'method' => 'post',
'args' => [
'fields' => PARAM_RAW
],
'response' => 'json'
],
'update' => [
'endpoint' => 'https://www.googleapis.com/drive/v3/files/{fileid}',
'method' => 'patch',
'args' => [
'fileid' => PARAM_RAW,
'fields' => PARAM_RAW,
'addParents' => PARAM_RAW,
'removeParents' => PARAM_RAW
],
'response' => 'json'
],
'create_permission' => [
'endpoint' => 'https://www.googleapis.com/drive/v3/files/{fileid}/permissions',
'method' => 'post',
'args' => [
'fileid' => PARAM_RAW,
'emailMessage' => PARAM_RAW,
'sendNotificationEmail' => PARAM_RAW,
'transferOwnership' => PARAM_RAW,
],
'response' => 'json'
],
'update_permission' => [
'endpoint' => 'https://www.googleapis.com/drive/v3/files/{fileid}/permissions/{permissionid}',
'method' => 'patch',
'args' => [
'fileid' => PARAM_RAW,
'permissionid' => PARAM_RAW,
'emailMessage' => PARAM_RAW,
'sendNotificationEmail' => PARAM_RAW,
'transferOwnership' => PARAM_RAW,
],
'response' => 'json'
],
'shared_drives_list' => [
'endpoint' => 'https://www.googleapis.com/drive/v3/drives',
'method' => 'get',
'args' => [
'pageSize' => PARAM_INT,
'pageToken' => PARAM_RAW,
'q' => PARAM_RAW,
'useDomainAdminAccess' => PARAM_RAW,
],
'response' => 'json',
],
];
}
}
+36
View File
@@ -0,0 +1,36 @@
<?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/>.
/**
* Plugin capabilities.
*
* @package repository_googledocs
* @copyright 2009 Dan Poltawski <talktodan@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$capabilities = array(
'repository/googledocs:view' => array(
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'user' => CAP_ALLOW
)
)
);
+43
View File
@@ -0,0 +1,43 @@
<?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/>.
/**
* Googledocs repository cache definitions.
*
* This file is part of Moodle's cache API, affectionately called MUC.
* It contains the components that are requried in order to use caching.
*
* @package repository_googledocs
* @copyright 2017 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$definitions = array(
// Used to store file ids for folders.
// The keys used are full path to the folder, the values are the id in google drive.
// The static acceleration size has been based upon the depths of a single path.
'folder' => array(
'mode' => cache_store::MODE_APPLICATION,
'simplekeys' => false,
'simpledata' => true,
'staticacceleration' => true,
'staticaccelerationsize' => 10,
'canuselocalstore' => true
),
);
+35
View File
@@ -0,0 +1,35 @@
<?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/>.
/**
* @param int $oldversion the version we are upgrading from
* @return bool result
*/
function xmldb_repository_googledocs_upgrade($oldversion) {
// Automatically generated Moodle v4.1.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.2.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.3.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.4.0 release upgrade line.
// Put any upgrade step following this.
return true;
}
@@ -0,0 +1,50 @@
<?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/>.
/**
* Strings for component 'repository_googledocs', language 'en', branch 'MOODLE_20_STABLE'
*
* @package repository_googledocs
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['configplugin'] = 'Configure Google Drive plugin';
$string['docsformat'] = 'Default document import format';
$string['drawingformat'] = 'Default drawing import format';
$string['googledocs:view'] = 'View Google Drive repository';
$string['importformat'] = 'Configure the default import formats from Google';
$string['mydrive'] = 'My Drive';
$string['pluginname'] = 'Google Drive';
$string['presentationformat'] = 'Default presentation import format';
$string['shareddrives'] = 'Shared Drives';
$string['spreadsheetformat'] = 'Default spreadsheet import format';
$string['issuer'] = 'OAuth 2 service';
$string['issuer_help'] = 'Select the OAuth 2 service that is configured to talk to the Google Drive API. If the service does not exist yet, you will need to create it.';
$string['servicenotenabled'] = 'Access not configured. Make sure the service \'Drive API\' is enabled.';
$string['oauth2serviceslink'] = '<a href="{$a}" title="Link to OAuth 2 services configuration">OAuth 2 services configuration</a>';
$string['searchfor'] = 'Search results for:';
$string['internal'] = 'Internal (files stored in Moodle)';
$string['external'] = 'External (only links stored in Moodle)';
$string['both'] = 'Internal and external';
$string['supportedreturntypes'] = 'Supported files';
$string['defaultreturntype'] = 'Default return type';
$string['fileoptions'] = 'The types and defaults for returned files is configurable here. Note that all files linked externally will be updated so that the owner is the Moodle system account.';
$string['owner'] = 'Owned by: {$a}';
$string['cachedef_folder'] = 'Google file IDs for folders in the system account';
$string['privacy:metadata:repository_googledocs'] = 'The Google Drive repository plugin does not store any personal data, but does transmit user data from Moodle to the remote system.';
$string['privacy:metadata:repository_googledocs:email'] = 'The email of the Google Drive repository user.';
$string['privacy:metadata:repository_googledocs:searchtext'] = 'The Google Drive repository user search text query.';
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

@@ -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/>.
/**
* Google Docs repository data generator
*
* @package repository_googledocs
* @category test
* @copyright 2013 Frédéric Massart
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use \core\oauth2\issuer;
use \core\oauth2\endpoint;
/**
* Google Docs repository data generator class
*
* @package repository_googledocs
* @category test
* @copyright 2013 Frédéric Massart
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class repository_googledocs_generator extends testing_repository_generator {
/**
* Fill in type record defaults.
*
* @param array $record
* @return array
*/
protected function prepare_type_record(array $record) {
$record = parent::prepare_type_record($record);
$issuerrecord = (object) [
'name' => 'Google',
'image' => 'https://accounts.google.com/favicon.ico',
'baseurl' => 'https://accounts.google.com/',
'loginparamsoffline' => 'access_type=offline&prompt=consent',
'showonloginpage' => issuer::EVERYWHERE
];
$issuer = new issuer(0, $issuerrecord);
$issuer->create();
$endpointrecord = (object) [
'issuerid' => $issuer->get('id'),
'name' => 'discovery_endpoint',
'url' => 'https://accounts.google.com/.well-known/openid-configuration'
];
$endpoint = new endpoint(0, $endpointrecord);
$endpoint->create();
if (!isset($record['issuerid'])) {
$record['issuerid'] = $issuer->get('id');
}
if (!isset($record['defaultreturntype'])) {
$record['defaultreturntype'] = FILE_INTERNAL;
}
if (!isset($record['supportedreturntypes'])) {
$record['supportedreturntypes'] = 'both';
}
if (!isset($record['documentformat'])) {
$record['documentformat'] = 'pdf';
}
if (!isset($record['presentationformat'])) {
$record['presentationformat'] = 'pdf';
}
if (!isset($record['drawingformat'])) {
$record['drawingformat'] = 'pdf';
}
if (!isset($record['spreadsheetformat'])) {
$record['spreadsheetformat'] = 'pdf';
}
return $record;
}
}
@@ -0,0 +1,54 @@
<?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/>.
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/repository/googledocs/tests/repository_googledocs_testcase.php');
/**
* Base class for the googledoc repository unit tests related to content browsing and searching.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class googledocs_content_testcase extends repository_googledocs_testcase {
/** @var array The array which contains the disallowed file extensions. */
protected $disallowedextensions = [];
/**
* Method used for filtering repository file nodes based on the current disallowed file extensions list.
*
* @param array $content The repository content node
* @return bool If returns false, the repository content node should be filtered, otherwise do not filter.
*/
public function filter(array $content): bool {
// If the disallowed file extensions list is empty, do not filter the content node.
if (empty($this->disallowedextensions)) {
return true;
}
foreach ($this->disallowedextensions as $extension) {
// If the disallowed file extension matches the extension of the repository file node,
// than filter this node.
if (preg_match("#.{$extension}#i", $content['title'])) {
return false;
}
}
return true;
}
}
@@ -0,0 +1,198 @@
<?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 repository_googledocs;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/repository/googledocs/tests/googledocs_content_testcase.php');
require_once($CFG->dirroot . '/repository/googledocs/lib.php');
/**
* Class containing unit tests for the search content class.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class googledocs_search_content_test extends \googledocs_content_testcase {
/**
* Test get_content_nodes().
*
* @dataProvider get_content_nodes_provider
* @param string $query The query string
* @param bool $sortcontent Whether the contents should be sorted in alphabetical order
* @param array $filterextensions The array containing file extensions that should be disallowed (filtered)
* @param array $shareddrives The array containing the existing shared drives
* @param array $searccontents The array containing the fetched google drive contents that match the search criteria
* @param array $expected The expected array which contains the generated repository content nodes
*/
public function test_get_content_nodes(string $query, bool $sortcontent, array $filterextensions,
array $shareddrives, array $searccontents, array $expected): void {
// Mock the service object.
$servicemock = $this->createMock(rest::class);
$searchparams = [
'q' => "fullText contains '" . str_replace("'", "\'", $query) . "' AND trashed = false",
'fields' => 'files(id,name,mimeType,webContentLink,webViewLink,fileExtension,modifiedTime,size,iconLink)',
'spaces' => 'drive',
];
if (!empty($shareddrives)) {
$searchparams['supportsAllDrives'] = 'true';
$searchparams['includeItemsFromAllDrives'] = 'true';
$searchparams['corpora'] = 'allDrives';
}
// Assert that the call() method is being called twice with the given arguments consecutively. In the first
// instance it is being called to fetch the shared drives (shared_drives_list), while in the second instance
// to fetch the relevant drive contents (list) that match the search criteria. Also, define the returned
// data objects by these calls.
$servicemock->expects($this->exactly(2))
->method('call')
->withConsecutive(
[
'shared_drives_list',
[],
],
[
'list',
$searchparams,
]
)
->willReturnOnConsecutiveCalls(
(object)[
'kind' => 'drive#driveList',
'nextPageToken' => 'd838181f30b0f5',
'drives' => $shareddrives,
],
(object)[
'files' => $searccontents,
]
);
// Construct the node path.
$path = \repository_googledocs::REPOSITORY_ROOT_ID . '|' . urlencode('Google Drive') . '/' .
\repository_googledocs::SEARCH_ROOT_ID . '|' . urlencode(
get_string('searchfor', 'repository_googledocs') . " '{$query}'");
$searchcontentobj = new googledocs_content_search($servicemock, $path, $sortcontent);
$this->disallowedextensions = $filterextensions;
$contentnodes = $searchcontentobj->get_content_nodes($query, [$this, 'filter']);
// Assert that the returned array of repository content nodes is equal to the expected one.
$this->assertEquals($expected, $contentnodes);
}
/**
* Data provider for test_get_content_nodes().
*
* @return array
*/
public function get_content_nodes_provider(): array {
$rootid = \repository_googledocs::REPOSITORY_ROOT_ID;
$searchnodeid = \repository_googledocs::SEARCH_ROOT_ID;
$searchforstring = get_string('searchfor', 'repository_googledocs');
return [
'Folders and files match the search criteria; shared drives exist; ordering applied.' =>
[
'test',
true,
[],
[
$this->create_google_drive_shared_drive_object('d85b21c0f86cb5', 'Shared Drive 1'),
],
[
$this->create_google_drive_file_object('d85b21c0f86cb0', 'Test file 3.pdf',
'application/pdf', 'pdf', '1000', '',
'https://drive.google.com/uc?id=d85b21c0f86cb0&export=download'),
$this->create_google_drive_folder_object('0c4ad262c65333', 'Test folder 1'),
$this->create_google_drive_file_object('bed5a0f08d412a', 'Test file 1.pdf',
'application/pdf', 'pdf'),
$this->create_google_drive_folder_object('9c4ad262c65333', 'Test folder 2'),
],
[
$this->create_folder_content_node_array('0c4ad262c65333', 'Test folder 1',
"{$rootid}|Google+Drive/{$searchnodeid}|" . urlencode("{$searchforstring} 'test'")),
$this->create_folder_content_node_array('9c4ad262c65333', 'Test folder 2',
"{$rootid}|Google+Drive/{$searchnodeid}|" . urlencode("{$searchforstring} 'test'")),
$this->create_file_content_node_array('bed5a0f08d412a', 'Test file 1.pdf',
'Test file 1.pdf', null, '', 'https://googleusercontent.com/type/application/pdf',
'', 'download'),
$this->create_file_content_node_array('d85b21c0f86cb0', 'Test file 3.pdf',
'Test file 3.pdf', '1000', '', 'https://googleusercontent.com/type/application/pdf',
'https://drive.google.com/uc?id=d85b21c0f86cb0&export=download', 'download'),
],
],
'Only folders match the search criteria; shared drives do not exist; ordering not applied.' =>
[
'testing',
false,
[],
[],
[
$this->create_google_drive_folder_object('0c4ad262c65333', 'Testing folder 3'),
$this->create_google_drive_folder_object('d85b21c0f86cb0', 'Testing folder 1'),
$this->create_google_drive_folder_object('bed5a0f08d412a', 'Testing folder 2'),
],
[
$this->create_folder_content_node_array('0c4ad262c65333', 'Testing folder 3',
"{$rootid}|Google+Drive/{$searchnodeid}|" . urlencode("{$searchforstring} 'testing'")),
$this->create_folder_content_node_array('d85b21c0f86cb0', 'Testing folder 1',
"{$rootid}|Google+Drive/{$searchnodeid}|" . urlencode("{$searchforstring} 'testing'")),
$this->create_folder_content_node_array('bed5a0f08d412a', 'Testing folder 2',
"{$rootid}|Google+Drive/{$searchnodeid}|" . urlencode("{$searchforstring} 'testing'")),
],
],
'Only files match the search criteria; shared drives exist; ordering not applied; filter .doc and .txt.' =>
[
'root',
false,
['doc', 'txt'],
[
$this->create_google_drive_shared_drive_object('d85b21c0f86cb5', 'Shared Drive 1'),
],
[
$this->create_google_drive_file_object('d85b21c0f86cb0', 'Testing file 3.pdf',
'application/pdf', 'pdf', '1000'),
$this->create_google_drive_file_object('a85b21c0f86cb0', 'Testing file 1.txt',
'text/plain', 'txt', '3000'),
$this->create_google_drive_file_object('f85b21c0f86cb0', 'Testing file 2.doc',
'application/msword', 'doc', '2000'),
],
[
$this->create_file_content_node_array('d85b21c0f86cb0', 'Testing file 3.pdf',
'Testing file 3.pdf', '1000', '',
'https://googleusercontent.com/type/application/pdf', '', 'download'),
],
],
'No content that matches the search criteria; shared drives do not exist.' =>
[
'root',
false,
[],
[],
[],
[],
],
];
}
}
+281
View File
@@ -0,0 +1,281 @@
<?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 repository_googledocs;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/repository/googledocs/tests/repository_googledocs_testcase.php');
require_once($CFG->dirroot . '/repository/googledocs/lib.php');
/**
* Class containing unit tests for the helper class.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class helper_test extends \repository_googledocs_testcase {
/**
* Test build_node_path().
*
* @dataProvider build_node_path_provider
* @param string $id The ID of the node
* @param string $name The name of the node
* @param string $rootpath The path to append the node on
* @param string $expected The expected node path
*/
public function test_build_node_path(string $id, string $name, string $rootpath, string $expected): void {
// Assert that the returned node path is equal to the expected one.
$this->assertEquals($expected, helper::build_node_path($id, $name, $rootpath));
}
/**
* Data provider for test_build_node_path().
*
* @return array
*/
public function build_node_path_provider(): array {
$rootid = \repository_googledocs::REPOSITORY_ROOT_ID;
$mydriveid = \repository_googledocs::MY_DRIVE_ROOT_ID;
$shareddrivesid = \repository_googledocs::SHARED_DRIVES_ROOT_ID;
return [
'Generate the path for a node without a root path.' =>
[
$rootid,
'Google Drive',
'',
"{$rootid}|Google+Drive",
],
'Generate the path for a node without a name and root path.' =>
[
$rootid,
'',
'',
$rootid,
],
'Generate the path for a node without a name.' =>
[
$mydriveid,
'',
"{$rootid}|Google+Drive",
"{$rootid}|Google+Drive/{$mydriveid}",
],
'Generate the path for a node which has a name and root path.' =>
[
'092cdf4732b9d5',
'Shared Drive 5',
"{$rootid}|Google+Drive/{$shareddrivesid}|Shared+Drives",
"{$rootid}|Google+Drive/{$shareddrivesid}|Shared+Drives/092cdf4732b9d5|Shared+Drive+5",
],
];
}
/**
* Test explode_node_path().
*
* @dataProvider explode_node_path_provider
* @param string $node The node string to extract information from
* @param array $expected The expected array containing the information about the node
*/
public function test_explode_node_path(string $node, array $expected): void {
// Assert that the returned array is equal to the expected one.
$this->assertEquals($expected, helper::explode_node_path($node));
}
/**
* Data provider for test_explode_node_path().
*
* @return array
*/
public function explode_node_path_provider(): array {
$rootid = \repository_googledocs::REPOSITORY_ROOT_ID;
return [
'Return the information for a path node that has a name.' =>
[
"{$rootid}|Google+Drive",
[
0 => $rootid,
1 => 'Google Drive',
'id' => $rootid,
'name' => 'Google Drive',
],
],
'Return the information for a path node that does not have a name.' =>
[
$rootid,
[
0 => $rootid,
1 => '',
'id' => $rootid,
'name' => '',
],
],
];
}
/**
* Test get_browser().
*
* @dataProvider get_browser_provider
* @param string $nodepath The node path string
* @param string $expected The expected browser class
*/
public function test_get_browser(string $nodepath, string $expected): void {
// The service (rest API) object is required by get_browser(), but not being used to determine which browser
// object should be returned. Therefore, we can simply mock this object in this test.
$servicemock = $this->createMock(rest::class);
$browser = helper::get_browser($servicemock, $nodepath);
// Assert that the returned browser class by get_browser() is equal to the expected one.
$this->assertEquals($expected, get_class($browser));
}
/**
* Data provider for test_get_browser().
*
* @return array
*/
public function get_browser_provider(): array {
$rootid = \repository_googledocs::REPOSITORY_ROOT_ID;
$mydriveid = \repository_googledocs::MY_DRIVE_ROOT_ID;
$shareddrivesid = \repository_googledocs::SHARED_DRIVES_ROOT_ID;
return [
'Repository root level path.' =>
[
"{$rootid}|Google+Drive",
\repository_googledocs\local\browser\googledocs_root_content::class,
],
'My drive path.' =>
[
"{$rootid}|Google+Drive/{$mydriveid}|My+Drive",
\repository_googledocs\local\browser\googledocs_drive_content::class,
],
'Shared drives root path.' =>
[
"{$rootid}|Google+Drive/{$shareddrivesid}|Shared+Drives",
\repository_googledocs\local\browser\googledocs_shared_drives_content::class,
],
'Path within a shared drive.' =>
[
"{$rootid}|Google+Drive/{$shareddrivesid}|Shared+Drives/092cdf4732b9d5|Shared+Drive+5",
\repository_googledocs\local\browser\googledocs_drive_content::class,
],
];
}
/**
* Test get_node().
*
* @dataProvider get_node_provider
* @param \stdClass $gdcontent The Google Drive content (file/folder) object
* @param string $expected The expected content node class
*/
public function test_get_node(\stdClass $gdcontent, string $expected): void {
// The path is required by get_content_node(), but not being used to determine which content node
// object should be returned. Therefore, we can just generate a dummy path.
$path = \repository_googledocs::REPOSITORY_ROOT_ID . '|Google+Drive|' .
\repository_googledocs::MY_DRIVE_ROOT_ID . '|My+Drive';
$node = helper::get_node($gdcontent, $path);
// Assert that the returned content node class by get_node() is equal to the expected one.
$this->assertEquals($expected, get_class($node));
}
/**
* Data provider for test_get_node().
*
* @return array
*/
public function get_node_provider(): array {
return [
'The content object represents a Google Drive folder.' =>
[
$this->create_google_drive_folder_object('e3b0c44298fc1c149', 'Folder', ''),
\repository_googledocs\local\node\folder_node::class,
],
'The content object represents a Google Drive file.' =>
[
$this->create_google_drive_file_object('de04d58dc5ccc', 'File.pdf',
'application/pdf'),
\repository_googledocs\local\node\file_node::class,
],
];
}
/**
* Test request() when an exception is thrown by the API call.
*
* @dataProvider request_exception_provider
* @param \Exception $exception The exception thrown by the API call
* @param \Exception $expected The expected exception thrown by request()
*/
public function test_request_exception(\Exception $exception, \Exception $expected): void {
// Mock the service object.
$servicemock = $this->createMock(rest::class);
// Assert that the call() method is being called only once with the given arguments.
// Define the thrown exception by this call.
$servicemock->expects($this->once())
->method('call')
->with('list', [])
->willThrowException($exception);
$this->expectExceptionObject($expected);
helper::request($servicemock, 'list', []);
}
/**
* Data provider for test_request_exception().
*
* @return array
*/
public function request_exception_provider(): array {
return [
'The API call throws exception (status: 403; message: Access Not Configured).' =>
[
new \Exception('Access Not Configured', 403),
new \repository_exception('servicenotenabled', 'repository_googledocs'),
],
'The API call throws exception (status: 405; message: Access Not Configured).' =>
[
new \Exception('Access Not Configured', 405),
new \Exception('Access Not Configured', 405),
],
'The API call throws exception (status: 403; message: Access Forbidden).' =>
[
new \Exception('Access Forbidden', 403),
new \Exception('Access Forbidden', 403),
],
'The API call throws exception (status: 404; message: Not Found).' =>
[
new \Exception('Not Found', 404),
new \Exception('Not Found', 404),
],
];
}
}
@@ -0,0 +1,269 @@
<?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 repository_googledocs\local\browser;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/repository/googledocs/tests/googledocs_content_testcase.php');
require_once($CFG->dirroot . '/repository/googledocs/lib.php');
/**
* Class containing unit tests for the drive browser class.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class googledocs_drive_content_test extends \googledocs_content_testcase {
/**
* Test get_content_nodes().
*
* @dataProvider get_content_nodes_provider
* @param string $query The query string
* @param string $path The path
* @param bool $sortcontent Whether the contents should be sorted in alphabetical order
* @param array $filterextensions The array containing file extensions that should be disallowed (filtered)
* @param array $shareddrives The array containing the existing shared drives
* @param array $drivecontents The array containing the fetched google drive contents
* @param array $expected The expected array which contains the generated repository content nodes
*/
public function test_get_content_nodes(string $query, string $path, bool $sortcontent, array $filterextensions,
array $shareddrives, array $drivecontents, array $expected): void {
// Mock the service object.
$servicemock = $this->createMock(\repository_googledocs\rest::class);
$listparams = [
'q' => "'" . str_replace("'", "\'", $query) . "' in parents AND trashed = false",
'fields' => 'files(id,name,mimeType,webContentLink,webViewLink,fileExtension,modifiedTime,size,iconLink)',
'spaces' => 'drive',
];
if (!empty($shareddrives)) {
$listparams['supportsAllDrives'] = 'true';
$listparams['includeItemsFromAllDrives'] = 'true';
}
// Assert that the call() method is being called twice with the given arguments consecutively. In the first
// instance it is being called to fetch the shared drives (shared_drives_list), while in the second instance
// to fetch the relevant drive contents (list). Also, define the returned data objects by these calls.
$servicemock->expects($this->exactly(2))
->method('call')
->withConsecutive(
[
'shared_drives_list',
[],
],
[
'list',
$listparams,
]
)
->willReturnOnConsecutiveCalls(
(object)[
'kind' => 'drive#driveList',
'nextPageToken' => 'd838181f30b0f5',
'drives' => $shareddrives,
],
(object)[
'files' => $drivecontents,
]
);
// Set the disallowed file types (extensions).
$this->disallowedextensions = $filterextensions;
$drivebrowser = new googledocs_drive_content($servicemock, $path, $sortcontent);
$contentnodes = $drivebrowser->get_content_nodes($query, [$this, 'filter']);
// Assert that the returned array of repository content nodes is equal to the expected one.
$this->assertEquals($expected, $contentnodes);
}
/**
* Data provider for test_get_content_nodes().
*
* @return array
*/
public function get_content_nodes_provider(): array {
$rootid = \repository_googledocs::REPOSITORY_ROOT_ID;
$mydriveid = \repository_googledocs::MY_DRIVE_ROOT_ID;
return [
'Folders and files exist in the drive; shared drives exist; ordering applied.' =>
[
$mydriveid,
"{$rootid}|Google+Drive/{$mydriveid}|My+Drive",
true,
[],
[
$this->create_google_drive_shared_drive_object('d85b21c0f86cb5', 'Shared Drive 1'),
],
[
$this->create_google_drive_folder_object('1c4ad262c65333', 'Folder 2'),
$this->create_google_drive_file_object('d85b21c0f86cb0', 'File 3.pdf',
'application/pdf', 'pdf', '1000'),
$this->create_google_drive_folder_object('0c4ad262c65333', 'Folder 1'),
$this->create_google_drive_file_object('bed5a0f08d412a', 'File 1.pdf',
'application/pdf', 'pdf'),
],
[
$this->create_folder_content_node_array('0c4ad262c65333', 'Folder 1',
"{$rootid}|Google+Drive/{$mydriveid}|My+Drive"),
$this->create_folder_content_node_array('1c4ad262c65333', 'Folder 2',
"{$rootid}|Google+Drive/{$mydriveid}|My+Drive"),
$this->create_file_content_node_array('bed5a0f08d412a', 'File 1.pdf', 'File 1.pdf',
null, '', 'https://googleusercontent.com/type/application/pdf', '',
'download'),
$this->create_file_content_node_array('d85b21c0f86cb0', 'File 3.pdf', 'File 3.pdf',
'1000', '', 'https://googleusercontent.com/type/application/pdf', '',
'download'),
],
],
'Only folders exist in the drive; shared drives do not exist; ordering not applied.' =>
[
$mydriveid,
"{$rootid}|Google+Drive/{$mydriveid}|My+Drive",
false,
[],
[],
[
$this->create_google_drive_folder_object('0c4ad262c65333', 'Folder 3'),
$this->create_google_drive_folder_object('d85b21c0f86cb0', 'Folder 1'),
$this->create_google_drive_folder_object('bed5a0f08d412a', 'Folder 2'),
],
[
$this->create_folder_content_node_array('0c4ad262c65333', 'Folder 3',
"{$rootid}|Google+Drive/{$mydriveid}|My+Drive"),
$this->create_folder_content_node_array('d85b21c0f86cb0', 'Folder 1',
"{$rootid}|Google+Drive/{$mydriveid}|My+Drive"),
$this->create_folder_content_node_array('bed5a0f08d412a', 'Folder 2',
"{$rootid}|Google+Drive/{$mydriveid}|My+Drive"),
],
],
'Only files exist in the drive; shared drives do not exist; ordering not applied; filter .txt.' =>
[
$mydriveid,
"{$rootid}|Google+Drive/{$mydriveid}|My+Drive",
false,
['txt'],
[],
[
$this->create_google_drive_file_object('d85b21c0f86cb0', 'File 3.pdf',
'application/pdf', 'pdf', '1000'),
$this->create_google_drive_file_object('a85b21c0f86cb0', 'File 1.txt',
'text/plain', 'txt', '3000'),
$this->create_google_drive_file_object('f85b21c0f86cb0', 'File 2.doc',
'application/msword', 'doc', '2000'),
],
[
$this->create_file_content_node_array('d85b21c0f86cb0', 'File 3.pdf', 'File 3.pdf',
'1000', '', 'https://googleusercontent.com/type/application/pdf', '',
'download'),
$this->create_file_content_node_array('f85b21c0f86cb0', 'File 2.doc', 'File 2.doc',
'2000', '', 'https://googleusercontent.com/type/application/msword', '',
'download'),
],
],
'Contents do not exist in the drive; shared drives do not exist.' =>
[
$mydriveid,
"{$rootid}|Google+Drive/{$mydriveid}|My+Drive",
false,
[],
[],
[],
[],
],
];
}
/**
* Test get_navigation().
*
* @dataProvider get_navigation_provider
* @param string $nodepath The node path string
* @param array $expected The expected array containing the repository navigation nodes
*/
public function test_get_navigation(string $nodepath, array $expected): void {
// Mock the service object.
$servicemock = $this->createMock(\repository_googledocs\rest::class);
$drivebrowser = new googledocs_drive_content($servicemock, $nodepath);
$navigation = $drivebrowser->get_navigation();
// Assert that the returned array containing the navigation nodes is equal to the expected one.
$this->assertEquals($expected, $navigation);
}
/**
* Data provider for test_get_navigation().
*
* @return array
*/
public function get_navigation_provider(): array {
$rootid = \repository_googledocs::REPOSITORY_ROOT_ID;
$mydriveid = \repository_googledocs::MY_DRIVE_ROOT_ID;
return [
'Return navigation nodes array from path where all nodes have a name.' =>
[
"{$rootid}|Google+Drive/{$mydriveid}|My+Drive/bed5a0f08d|Test+Folder",
[
[
'name' => 'Google Drive',
'path' => "{$rootid}|Google+Drive",
],
[
'name' => 'My Drive',
'path' => "{$rootid}|Google+Drive/{$mydriveid}|My+Drive",
],
[
'name' => 'Test Folder',
'path' => "{$rootid}|Google+Drive/{$mydriveid}|My+Drive/bed5a0f08d|Test+Folder",
],
],
],
'Return navigation nodes array from path where some nodes do not have a name.' =>
[
"{$rootid}|Google+Drive/{$mydriveid}|My+Drive/bed5a0f08d/d85b21c0f8|Test+Folder",
[
[
'name' => 'Google Drive',
'path' => "{$rootid}|Google+Drive",
],
[
'name' => 'My Drive',
'path' => "{$rootid}|Google+Drive/{$mydriveid}|My+Drive",
],
[
'name' => 'bed5a0f08d',
'path' => "{$rootid}|Google+Drive/{$mydriveid}|My+Drive/bed5a0f08d|bed5a0f08d",
],
[
'name' => 'Test Folder',
'path' => "{$rootid}|Google+Drive/{$mydriveid}|My+Drive/bed5a0f08d|bed5a0f08d/" .
"d85b21c0f8|Test+Folder",
],
],
],
];
}
}
@@ -0,0 +1,102 @@
<?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 repository_googledocs\local\browser;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/repository/googledocs/tests/googledocs_content_testcase.php');
require_once($CFG->dirroot . '/repository/googledocs/lib.php');
/**
* Class containing unit tests for the repository root browser class.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class googledocs_root_content_test extends \googledocs_content_testcase {
/**
* Test get_content_nodes().
*
* @dataProvider get_content_nodes_provider
* @param array $shareddrives The array containing the existing shared drives
* @param array $expected The expected array which contains the generated repository content nodes
*/
public function test_get_content_nodes(array $shareddrives, array $expected): void {
// Mock the service object.
$servicemock = $this->createMock(\repository_googledocs\rest::class);
// Assert that the call() method is being called only once with the given arguments to fetch the existing
// shared drives. Define the returned data object by this call.
$servicemock->expects($this->once())
->method('call')
->with('shared_drives_list', [])
->willReturn((object)[
'kind' => 'drive#driveList',
'nextPageToken' => 'd838181f30b0f5',
'drives' => $shareddrives,
]);
$rootbrowser = new googledocs_root_content($servicemock,
\repository_googledocs::REPOSITORY_ROOT_ID . '|Google+Drive', false);
$contentnodes = $rootbrowser->get_content_nodes('', [$this, 'filter']);
// Assert that the returned array of repository content nodes is equal to the expected one.
$this->assertEquals($expected, $contentnodes);
}
/**
* Data provider for test_get_content_nodes().
*
* @return array
*/
public function get_content_nodes_provider(): array {
$rootid = \repository_googledocs::REPOSITORY_ROOT_ID;
$mydriveid = \repository_googledocs::MY_DRIVE_ROOT_ID;
$shareddrivesid = \repository_googledocs::SHARED_DRIVES_ROOT_ID;
return [
'Shared drives exist.' =>
[
[
$this->create_google_drive_shared_drive_object('d85b21c0f86cb5', 'Shared Drive 1'),
$this->create_google_drive_shared_drive_object('d85b21c0f86cb0', 'Shared Drive 3'),
],
[
$this->create_folder_content_node_array($mydriveid,
get_string('mydrive', 'repository_googledocs'),
"{$rootid}|Google+Drive"),
$this->create_folder_content_node_array($shareddrivesid,
get_string('shareddrives', 'repository_googledocs'),
"{$rootid}|Google+Drive"),
],
],
'Shared drives do not exist.' =>
[
[],
[
$this->create_folder_content_node_array($mydriveid,
get_string('mydrive', 'repository_googledocs'),
"{$rootid}|Google+Drive"),
],
],
];
}
}
@@ -0,0 +1,120 @@
<?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 repository_googledocs\local\browser;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/repository/googledocs/tests/googledocs_content_testcase.php');
require_once($CFG->dirroot . '/repository/googledocs/lib.php');
/**
* Class containing unit tests for the shared drives browser class.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class googledocs_shared_drives_content_test extends \googledocs_content_testcase {
/**
* Test get_content_nodes().
*
* @dataProvider get_content_nodes_provider
* @param array $shareddrives The array containing the existing shared drives
* @param bool $sortcontent Whether the contents should be sorted in alphabetical order
* @param array $expected The expected array which contains the generated repository content nodes
*/
public function test_get_content_nodes(array $shareddrives, bool $sortcontent, array $expected): void {
// Mock the service object.
$servicemock = $this->createMock(\repository_googledocs\rest::class);
// Assert that the call() method is being called only once with the given arguments to fetch the existing
// shared drives. Define the returned data object by this call.
$servicemock->expects($this->once())
->method('call')
->with('shared_drives_list', [])
->willReturn((object)[
'kind' => 'drive#driveList',
'nextPageToken' => 'd838181f30b0f5',
'drives' => $shareddrives,
]);
$path = \repository_googledocs::REPOSITORY_ROOT_ID . '|Google+Drive/' .
\repository_googledocs::SHARED_DRIVES_ROOT_ID . '|Shared+Drives';
$shareddrivesbrowser = new googledocs_shared_drives_content($servicemock, $path, $sortcontent);
$contentnodes = $shareddrivesbrowser->get_content_nodes('', [$this, 'filter']);
// Assert that the returned array of repository content nodes is equal to the expected one.
$this->assertEquals($expected, $contentnodes);
}
/**
* Data provider for test_get_content_nodes().
*
* @return array
*/
public function get_content_nodes_provider(): array {
$rootid = \repository_googledocs::REPOSITORY_ROOT_ID;
$shareddrivesid = \repository_googledocs::SHARED_DRIVES_ROOT_ID;
$shareddrivesstring = get_string('shareddrives', 'repository_googledocs');
return [
'Shared drives exist; ordering applied.' =>
[
[
$this->create_google_drive_shared_drive_object('d85b21c0f86cb5', 'Shared Drive 1'),
$this->create_google_drive_shared_drive_object('d85b21c0f86cb0', 'Shared Drive 3'),
$this->create_google_drive_shared_drive_object('bed5a0f08d412a', 'Shared Drive 2'),
],
true,
[
$this->create_folder_content_node_array('d85b21c0f86cb5', 'Shared Drive 1',
"{$rootid}|Google+Drive/{$shareddrivesid}|" . urlencode($shareddrivesstring)),
$this->create_folder_content_node_array('bed5a0f08d412a', 'Shared Drive 2',
"{$rootid}|Google+Drive/{$shareddrivesid}|" . urlencode($shareddrivesstring)),
$this->create_folder_content_node_array('d85b21c0f86cb0', 'Shared Drive 3',
"{$rootid}|Google+Drive/{$shareddrivesid}|" . urlencode($shareddrivesstring)),
],
],
'Shared drives exist; ordering not applied.' =>
[
[
$this->create_google_drive_shared_drive_object('0c4ad262c65333', 'Shared Drive 3'),
$this->create_google_drive_shared_drive_object('d85b21c0f86cb0', 'Shared Drive 1'),
$this->create_google_drive_shared_drive_object('bed5a0f08d412a', 'Shared Drive 2'),
],
false,
[
$this->create_folder_content_node_array('0c4ad262c65333', 'Shared Drive 3',
"{$rootid}|Google+Drive/{$shareddrivesid}|" . urlencode($shareddrivesstring)),
$this->create_folder_content_node_array('d85b21c0f86cb0', 'Shared Drive 1',
"{$rootid}|Google+Drive/{$shareddrivesid}|" . urlencode($shareddrivesstring)),
$this->create_folder_content_node_array('bed5a0f08d412a', 'Shared Drive 2',
"{$rootid}|Google+Drive/{$shareddrivesid}|" . urlencode($shareddrivesstring)),
],
],
'Shared drives do not exist.' =>
[
[],
false,
[],
],
];
}
}
@@ -0,0 +1,123 @@
<?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 repository_googledocs\local\node;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/repository/googledocs/tests/repository_googledocs_testcase.php');
/**
* Class containing unit tests for the repository file node class.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class file_node_test extends \repository_googledocs_testcase {
/**
* Test create_node_array().
*
* @dataProvider create_node_array_provider
* @param \stdClass $gdfile The Google Drive file object
* @param array $configsettings The googledoc repository config settings that should be set
* @param array|null $expected The expected repository file node array
*/
public function test_create_node_array(\stdClass $gdfile, array $configsettings, ?array $expected): void {
$this->resetAfterTest();
// Set the required config settings.
array_walk($configsettings, function($value, $name) {
set_config($name, $value, 'googledocs');
});
$filenode = new file_node($gdfile);
$filenodearray = $filenode->create_node_array();
// Assert that the returned repository file node array by create_node_array() is equal to the expected one.
$this->assertEquals($expected, $filenodearray);
}
/**
* Data provider for test_create_node_array().
*
* @return array
*/
public function create_node_array_provider(): array {
return [
'Google Drive file with an extension.' =>
[
$this->create_google_drive_file_object('d85b21c0f86cb0', 'File.pdf',
'application/pdf', 'pdf', '1000', '01/01/21 0:30'),
[],
$this->create_file_content_node_array('d85b21c0f86cb0', 'File.pdf', 'File.pdf', '1000',
'1609432200', 'https://googleusercontent.com/type/application/pdf', '',
'download'),
],
'Google Drive file that has webContentLink and webViewLink.' =>
[
$this->create_google_drive_file_object('d85b21c0f86cb0', 'File.pdf',
'application/pdf', 'pdf', null, '',
'https://drive.google.com/uc?id=d85b21c0f86cb0&export=download',
'https://drive.google.com/file/d/d85b21c0f86cb0/view?usp=drivesdk'),
[
'documentformat' => 'rtf',
],
$this->create_file_content_node_array('d85b21c0f86cb0', 'File.pdf', 'File.pdf', null,
'', 'https://googleusercontent.com/type/application/pdf',
'https://drive.google.com/file/d/d85b21c0f86cb0/view?usp=drivesdk', 'download'),
],
'Google Drive file that has webContentLink and no webViewLink.' =>
[
$this->create_google_drive_file_object('d85b21c0f86cb0', 'File.pdf',
'application/pdf', 'pdf', null, '',
'https://drive.google.com/uc?id=d85b21c0f86cb0&export=download', ''),
[],
$this->create_file_content_node_array('d85b21c0f86cb0', 'File.pdf', 'File.pdf', null,
'', 'https://googleusercontent.com/type/application/pdf',
'https://drive.google.com/uc?id=d85b21c0f86cb0&export=download', 'download'),
],
'Google Drive file without an extension (Google document file; documentformat config set to rtf).' =>
[
$this->create_google_drive_file_object('d85b21c0f86cb0', 'File',
'application/vnd.google-apps.document', null),
[
'documentformat' => 'rtf',
],
$this->create_file_content_node_array('d85b21c0f86cb0', 'File', 'File.gdoc', '', '',
'https://googleusercontent.com/type/application/vnd.google-apps.document', '',
'application/rtf', 'document'),
],
'Google Drive file without an extension (Google presentation file; presentationformat config not set).' =>
[
$this->create_google_drive_file_object('d85b21c0f86cb0', 'File',
'application/vnd.google-apps.presentation', null),
[
'documentformat' => 'rtf',
],
null,
],
'Google Drive file without an extension (File type not supported).' =>
[
$this->create_google_drive_file_object('d85b21c0f86cb0', 'File',
'application/vnd.google-apps.unknownmimetype', null),
[],
null,
],
];
}
}
@@ -0,0 +1,73 @@
<?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 repository_googledocs\local\node;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/repository/googledocs/tests/repository_googledocs_testcase.php');
/**
* Class containing unit tests for the repository folder node class.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class folder_node_test extends \repository_googledocs_testcase {
/**
* Test create_node_array().
*
* @dataProvider create_node_array_provider
* @param \stdClass $gdfolder The Google Drive folder object
* @param string $path The current path
* @param array $expected The expected repository folder node array
*/
public function test_create_node_array(\stdClass $gdfolder, string $path, array $expected): void {
$foldernode = new folder_node($gdfolder, $path);
$foldernodearray = $foldernode->create_node_array();
// Assert that the returned repository folder node array by create_node_array() is equal to the expected one.
$this->assertEquals($expected, $foldernodearray);
}
/**
* Data provider for test_create_node_array().
*
* @return array
*/
public function create_node_array_provider(): array {
$rootid = \repository_googledocs::REPOSITORY_ROOT_ID;
return [
'Google Drive folder with modified date.' =>
[
$this->create_google_drive_folder_object('d85b21c0f86cb0', 'Folder', '01/01/21 0:30'),
"{$rootid}|Google+Drive",
$this->create_folder_content_node_array('d85b21c0f86cb0', 'Folder',
"{$rootid}|Google+Drive", '1609432200'),
],
'Google Drive folder without modified date.' =>
[
$this->create_google_drive_folder_object('d85b21c0f86cb0', 'Folder', ''),
'',
$this->create_folder_content_node_array('d85b21c0f86cb0', 'Folder', '', ''),
],
];
}
}
@@ -0,0 +1,156 @@
<?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/>.
/**
* Base class for the googledoc repository unit tests.
*
* @package repository_googledocs
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class repository_googledocs_testcase extends \advanced_testcase {
/**
* Create an array that would replicate the structure of a repository folder node array.
*
* @param string $id The ID of the folder
* @param string $name The name of the folder
* @param string $path The root path
* @param string $modified The date of the last modification
* @return array The repository folder node array
*/
protected function create_folder_content_node_array(string $id, string $name, string $path,
string $modified = ''): array {
global $CFG, $OUTPUT;
return [
'id' => $id,
'title' => $name,
'path' => repository_googledocs\helper::build_node_path($id, $name, $path),
'date' => $modified,
'thumbnail' => "{$CFG->wwwroot}/theme/image.php/boost/core/1/" . file_folder_icon(),
'thumbnail_height' => 64,
'thumbnail_width' => 64,
'children' => [],
];
}
/**
* Create an array that would replicate the structure of a repository file node array.
*
* @param string $id The ID of the file
* @param string $name The name of the file
* @param string $title The title of the file node
* @param string|null $size The size of the file
* @param string $modified The date of the last modification
* @param string $thumbnail The thumbnail of the file
* @param string|null $link The external link to the file
* @param string|null $exportformat The export format of the file
* @param string|null $googledoctype The type of the Google Doc file (if applicable)
* @return array The repository file node array
*/
protected function create_file_content_node_array(string $id, string $name, string $title, ?string $size = null,
string $modified = '', string $thumbnail = '' , string $link = '', string $exportformat = '',
?string $googledoctype = null): array {
return [
'id' => $id,
'title' => $title,
'source' => json_encode([
'id' => $id,
'name' => $name,
'link' => $link,
'exportformat' => $exportformat,
'googledoctype' => $googledoctype
]),
'date' => $modified,
'size' => $size,
'thumbnail' => $thumbnail,
'thumbnail_height' => 64,
'thumbnail_width' => 64,
];
}
/**
* Create an object that would replicate the metadata for a shared drive returned by the Google Drive API call.
*
* @param string $id The ID of the shared drive
* @param string $name The name of the shared drive
* @return \stdClass The shared drive object
*/
protected function create_google_drive_shared_drive_object(string $id, string $name): \stdClass {
return (object)[
'kind' => 'drive#drive',
'id' => $id,
'name' => $name,
];
}
/**
* Create an object that would replicate the metadata for a folder returned by the Google Drive API call.
*
* @param string $id The ID of the folder
* @param string $name The name of the folder
* @param string|null $modified The date of the last modification
* @return \stdClass The folder object
*/
protected function create_google_drive_folder_object(string $id, string $name, ?string $modified = null): \stdClass {
return (object)[
'id' => $id,
'name' => $name,
'mimeType' => 'application/vnd.google-apps.folder',
'webViewLink' => "https://drive.google.com/drive/folders/{$id}",
'iconLink' => 'https://googleusercontent.com/16/type/application/vnd.google-apps.folder+shared',
'modifiedTime' => $modified ?? '',
];
}
/**
* Create an object that would replicate the metadata for a file returned by the Google Drive API call.
*
* @param string $id The ID of the file
* @param string $name The name of the file
* @param string $mimetype The mimetype of the file
* @param string|null $extension The extension of the file
* @param string|null $size The size of the file
* @param string|null $modified The date of the last modification
* @param string|null $webcontentlink The link for downloading the content of the file
* @param string|null $webviewlink The link for opening the file in a browser
* @return \stdClass The file object
*/
protected function create_google_drive_file_object(string $id, string $name, string $mimetype,
?string $extension = null, ?string $size = null, ?string $modified = null, ?string $webcontentlink = null,
?string $webviewlink = null): \stdClass {
$googledrivefile = [
'id' => $id,
'name' => $name,
'mimeType' => $mimetype,
'size' => $size ?? '',
'webContentLink' => $webcontentlink ?? '',
'webViewLink' => $webviewlink ?? '',
'iconLink' => "https://googleusercontent.com/type/{$mimetype}",
'modifiedTime' => $modified ?? '',
];
// The returned metadata might not always have the 'fileExtension' property.
if ($extension) {
$googledrivefile['fileExtension'] = $extension;
}
return (object)$googledrivefile;
}
}
+30
View File
@@ -0,0 +1,30 @@
<?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/>.
/**
* Version details
*
* @package repository
* @subpackage googledocs
* @copyright 2009 Dan Poltawski <talktodan@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2024042200; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2024041600; // Requires this Moodle version.
$plugin->component = 'repository_googledocs'; // Full name of the plugin (used for diagnostics).