File manager - Edit - /home/u466501803/domains/qurdis.my.id/public_html/files.zip
Back
PK b<�\��� classes/converter_interface.phpnu �[��� <?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/>. /** * Class for converting files between different file formats. * * @package core_files * @copyright 2017 Andrew Nicols <andrew@nicols.co.uk> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_files; defined('MOODLE_INTERNAL') || die(); /** * Class for converting files between different file formats. * * @package docconvert_unoconv * @copyright 2017 Andrew Nicols <andrew@nicols.co.uk> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ interface converter_interface { /** * Whether the plugin is configured and requirements are met. * * Note: This function may be called frequently and caching is advisable. * * @return bool */ public static function are_requirements_met(); /** * Convert a document to a new format and return a conversion object relating to the conversion in progress. * * @param conversion $conversion The file to be converted * @return $this */ public function start_document_conversion(conversion $conversion); /** * Poll an existing conversion for status update. * * @param conversion $conversion The file to be converted * @return $this */ public function poll_conversion_status(conversion $conversion); /** * Determine whether a conversion between the two supplied formats is achievable. * * Note: This function may be called frequently and caching is advisable. * * @param string $from The source type * @param string $to The destination type * @return bool */ public static function supports($from, $to); /** * A list of the supported conversions. * * Note: This information is only displayed to administrators. * * @return string */ public function get_supported_conversions(); } PK b<�\��X� � ! classes/external/delete/draft.phpnu �[��� <?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/>. /** * This is the external method for deleting draft files. * * @package core_files * @since Moodle 3.10 * @copyright 2020 Juan Leyva <juan@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_files\external\delete; defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->libdir . '/filelib.php'); use core_external\external_api; use core_external\external_function_parameters; use core_external\external_multiple_structure; use core_external\external_single_structure; use core_external\external_value; use core_external\external_warnings; use context_user; /** * This is the external method for deleting draft files. * * @copyright 2020 Juan Leyva <juan@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class draft extends external_api { /** * Describes the parameters for execute. * * @return external_function_parameters * @since Moodle 3.10 */ public static function execute_parameters(): external_function_parameters { return new external_function_parameters ( [ 'draftitemid' => new external_value(PARAM_INT, 'Item id of the draft file area'), 'files' => new external_multiple_structure( new external_single_structure( [ 'filepath' => new external_value(PARAM_PATH, 'Path to the file or directory to delete.'), 'filename' => new external_value(PARAM_FILE, 'Name of the file to delete.'), ] ), 'Files or directories to be deleted.' ), ] ); } /** * Delete the indicated files (or directories) from a user draft file area. * * @param int $draftitemid item id of the draft file area * @param array $files files to be deleted * @return array of warnings and parent paths of the files deleted * @since Moodle 3.10 */ public static function execute(int $draftitemid, array $files): array { global $CFG, $USER; require_once($CFG->dirroot . '/repository/lib.php'); $params = self::validate_parameters(self::execute_parameters(), compact('draftitemid', 'files')); [$draftitemid, $files] = array_values($params); $usercontext = context_user::instance($USER->id); self::validate_context($usercontext); $files = array_map(function($file) { return (object) $file; }, $files); $parentpaths = repository_delete_selected_files($usercontext, 'user', 'draft', $draftitemid, $files); return [ 'parentpaths' => array_keys($parentpaths), 'warnings' => [], ]; } /** * Describes the execute return value. * * @return external_single_structure * @since Moodle 3.10 */ public static function execute_returns(): external_single_structure { return new external_single_structure( [ 'parentpaths' => new external_multiple_structure( new external_value(PARAM_PATH, 'Path to parent directory of the deleted files.') ), 'warnings' => new external_warnings(), ] ); } } PK b<�\�Q % classes/external/get/unused_draft.phpnu �[��� <?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/>. /** * Generate a new draft itemid for the current user. * * @package core_files * @since Moodle 3.11 * @copyright 2020 Juan Leyva <juan@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_files\external\get; defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->libdir . '/filelib.php'); use core_external\external_api; use core_external\external_function_parameters; use core_external\external_single_structure; use core_external\external_value; use core_external\external_warnings; use context_user; /** * Generate a new draft itemid for the current user. * * @copyright 2020 Juan Leyva <juan@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class unused_draft extends external_api { /** * Describes the parameters for execute. * * @return external_function_parameters * @since Moodle 3.11 */ public static function execute_parameters(): external_function_parameters { return new external_function_parameters ([]); } /** * Generate a new draft itemid for the current user. * * @return array of information containing the draft item area and possible warnings. * @since Moodle 3.11 */ public static function execute(): array { global $USER; $usercontext = context_user::instance($USER->id); self::validate_context($usercontext); return [ 'component' => 'user', 'contextid' => $usercontext->id, 'userid' => $USER->id, 'filearea' => 'draft', 'itemid' => file_get_unused_draft_itemid(), 'warnings' => [], ]; } /** * Describes the execute return value. * * @return external_single_structure * @since Moodle 3.11 */ public static function execute_returns(): external_single_structure { return new external_single_structure( [ 'component' => new external_value(PARAM_COMPONENT, 'File area component.'), 'contextid' => new external_value(PARAM_INT, 'File area context.'), 'userid' => new external_value(PARAM_INT, 'File area user id.'), 'filearea' => new external_value(PARAM_ALPHA, 'File area name.'), 'itemid' => new external_value(PARAM_INT, 'File are item id.'), 'warnings' => new external_warnings(), ] ); } } PK b<�\=�s?� � ) classes/external/stored_file_exporter.phpnu �[��� <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. namespace core_files\external; use coding_exception; use core_text; use moodle_url; use renderer_base; use stdClass; use stored_file; /** * Class for exporting stored_file data. * * @package core_files * @copyright 2015 Frédéric Massart - FMCorz.net * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class stored_file_exporter extends \core\external\exporter { /** @var int Length of the shortened filename */ protected const FILENAMESHORT_LENGTH = 25; /** @var stored_file */ protected $file; public function __construct(stored_file $file, $related = array()) { $this->file = $file; $data = new stdClass(); $data->contextid = $file->get_contextid(); $data->component = $file->get_component(); $data->filearea = $file->get_filearea(); $data->itemid = $file->get_itemid(); $data->filepath = $file->get_filepath(); $data->filename = $file->get_filename(); $data->isdir = $file->is_directory(); $data->isimage = $file->is_valid_image(); $data->timemodified = $file->get_timemodified(); $data->timecreated = $file->get_timecreated(); $data->filesize = $file->get_filesize(); $data->author = $file->get_author(); $data->license = $file->get_license(); if ($related['context']->id != $data->contextid) { throw new coding_exception('Unexpected context ID received.'); } parent::__construct($data, $related); } protected static function define_related() { return array('context' => 'context'); } protected static function define_properties() { return array( 'contextid' => array( 'type' => PARAM_INT ), 'component' => array( 'type' => PARAM_COMPONENT ), 'filearea' => array( 'type' => PARAM_AREA ), 'itemid' => array( 'type' => PARAM_INT ), 'filepath' => array( 'type' => PARAM_PATH ), 'filename' => array( 'type' => PARAM_FILE ), 'isdir' => array( 'type' => PARAM_BOOL ), 'isimage' => array( 'type' => PARAM_BOOL ), 'timemodified' => array( 'type' => PARAM_INT ), 'timecreated' => array( 'type' => PARAM_INT ), 'filesize' => array( 'type' => PARAM_INT ), 'author' => array( 'type' => PARAM_TEXT ), 'license' => array( 'type' => PARAM_TEXT ) ); } protected static function define_other_properties() { return array( 'filenameshort' => array( 'type' => PARAM_RAW, ), 'filesizeformatted' => array( 'type' => PARAM_RAW ), 'icon' => array( 'type' => PARAM_RAW, ), 'timecreatedformatted' => array( 'type' => PARAM_RAW ), 'timemodifiedformatted' => array( 'type' => PARAM_RAW ), 'url' => array( 'type' => PARAM_URL ), ); } protected function get_other_values(renderer_base $output) { $filename = $this->file->get_filename(); $filenameshort = $filename; if (core_text::strlen($filename) > static::FILENAMESHORT_LENGTH) { $extension = pathinfo($filename, PATHINFO_EXTENSION); $extensionlength = core_text::strlen($extension) + 1; $filenameshort = core_text::substr($filename, 0, -$extensionlength); $filenameshort = shorten_text($filenameshort, static::FILENAMESHORT_LENGTH - $extensionlength, true, '..') . ".{$extension}"; } $icon = $this->file->is_directory() ? file_folder_icon() : file_file_icon($this->file); $url = moodle_url::make_pluginfile_url( $this->file->get_contextid(), $this->file->get_component(), $this->file->get_filearea(), $this->file->get_itemid(), $this->file->get_filepath(), $this->file->get_filename(), true ); return array( 'filenameshort' => $filenameshort, 'filesizeformatted' => display_size((int) $this->file->get_filesize()), 'icon' => $icon, 'url' => $url->out(false), 'timecreatedformatted' => userdate($this->file->get_timecreated()), 'timemodifiedformatted' => userdate($this->file->get_timemodified()), ); } } PK b<�\�c�� � $ classes/hook/before_file_created.phpnu �[��� <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. namespace core_files\hook; use core\exception\coding_exception; use core\attribute; /** * A hook which is fired before a file is created in the file storage API. * * @package core_files * @copyright 2024 Andrew Lyons <andrew@nicols.co.uk> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ #[attribute\label('Allows subscribers to modify file content before it is stored in the file pool')] #[attribute\tags('file')] #[attribute\hook\replaces_callbacks('before_file_created')] final class before_file_created { use \core\hook\stoppable_trait; /** @var bool Whether the content has been updated at all */ public bool $contentupdated = false; /** * Constructor. * * @param \stdClass|null $filerecord * @param string|null $filepath The path to the file on disk * @param string|null $filecontent The content of the file */ public function __construct( /** @var \stdClass The file record */ protected ?\stdClass $filerecord = null, /** @var string|null $filepath The source file on disk */ protected ?string $filepath = null, /** @var string|null $filecontent The content of the file if it is not stored on disk */ protected ?string $filecontent = null, ) { if ($filepath === null && $filecontent === null) { throw new \InvalidArgumentException('Either $filepath or $filecontent must be set'); } if ($filepath !== null && $filecontent !== null) { throw new \InvalidArgumentException('Only one of $filepath or $filecontent can be set'); } } /** * Whether the file path was specified. * * @return bool */ public function has_filepath(): bool { return $this->filepath !== null; } /** * Whether the file content was specified. * * @return bool */ public function has_filecontent(): bool { return $this->filecontent !== null; } /** * Get the file path to the file that will be stored. * * @return string */ public function get_filepath(): ?string { return $this->filepath; } /** * Get the file content that will be stored. * * @return string */ public function get_filecontent(): ?string { return $this->filecontent; } /** * Get the file record. * * @return \stdClass|null */ public function get_filerecord(): ?\stdClass { return $this->filerecord; } /** * Update the file path to a new value. * * @param string $filepath */ public function update_filepath(string $filepath): void { if ($this->filepath === null) { throw new coding_exception('Cannot update file path when the file path is not set'); } if ($filepath !== $this->filepath) { $this->contentupdated = true; $this->filepath = $filepath; } } /** * Update the file content to a new value. * * @param string $filecontent */ public function update_filecontent(string $filecontent): void { if ($this->filecontent === null) { throw new coding_exception('Cannot update file content when the file content is not set'); } if ($filecontent !== $this->filecontent) { $this->contentupdated = true; $this->filecontent = $filecontent; } } /** * Whether the file path or file content has been changed. * * @return bool */ public function has_changed(): bool { return $this->contentupdated; } /** * Process legacy callbacks. */ public function process_legacy_callbacks(): void { if ($pluginsfunction = get_plugins_with_function(function: 'before_file_created', migratedtohook: true)) { foreach ($pluginsfunction as $plugintype => $plugins) { foreach ($plugins as $pluginfunction) { $pluginfunction($this->filerecord); } } } } } PK b<�\����Q Q # classes/hook/after_file_created.phpnu �[��� <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. namespace core_files\hook; use core\attribute; use core\hook\stoppable_trait; /** * A hook which is fired after a file is created in the file storage API. * * @package core * @copyright 2024 Huong Nguyen <huongnv13@gmail.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ #[attribute\label('Allows subscribers to inspect a file after it is created in the file pool')] #[attribute\tags('file')] #[attribute\hook\replaces_callbacks('after_file_created')] final class after_file_created { use stoppable_trait; /** * Hook to allow subscribers to modify file after it is created. * * @param \stored_file $storedfile The stored file. * @param \stdClass $filerecord The file record. */ public function __construct( /** @var \stored_file The stored file. */ public readonly \stored_file $storedfile, /** @var \stdClass The file record. */ public readonly \stdClass $filerecord, ) { } /** * Process legacy callbacks. */ public function process_legacy_callbacks(): void { if ($pluginsfunction = get_plugins_with_function(function: 'after_file_created', migratedtohook: true)) { foreach ($pluginsfunction as $plugintype => $plugins) { foreach ($plugins as $pluginfunction) { $pluginfunction($this->filerecord); } } } } } PK b<�\�0�<V V classes/privacy/provider.phpnu �[��� <?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/>. /** * Data provider. * * @package core_files * @copyright 2018 Frédéric Massart * @author Frédéric Massart <fred@branchup.tech> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_files\privacy; defined('MOODLE_INTERNAL') || die(); use core_privacy\local\metadata\collection; use core_privacy\local\request\contextlist; use core_privacy\local\request\approved_contextlist; use core_privacy\local\request\userlist; use core_privacy\local\request\approved_userlist; /** * Data provider class. * * This only describes the files table, all components must handle the file exporting * and deletion themselves. * * @package core_files * @copyright 2018 Frédéric Massart * @author Frédéric Massart <fred@branchup.tech> * @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\subsystem\plugin_provider, \core_privacy\local\request\core_userlist_provider, // We store a userkey for token-based file access. \core_privacy\local\request\subsystem\provider, \core_privacy\local\request\shared_userlist_provider { /** * Returns metadata. * * @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_database_table('files', [ 'contenthash' => 'privacy:metadata:files:contenthash', 'filepath' => 'privacy:metadata:files:filepath', 'filename' => 'privacy:metadata:files:filename', 'userid' => 'privacy:metadata:files:userid', 'filesize' => 'privacy:metadata:files:filesize', 'mimetype' => 'privacy:metadata:files:mimetype', 'source' => 'privacy:metadata:files:source', 'author' => 'privacy:metadata:files:author', 'license' => 'privacy:metadata:files:license', 'timecreated' => 'privacy:metadata:files:timecreated', 'timemodified' => 'privacy:metadata:files:timemodified', ], 'privacy:metadata:files'); // Regarding this block, we are unable to export or purge this data, as // it would damage the file conversion data across the whole site. $collection->add_database_table('file_conversion', [ 'usermodified' => 'privacy:metadata:file_conversion:usermodified', ], 'privacy:metadata:file_conversions'); $collection->add_subsystem_link('core_userkey', [], 'privacy:metadata:core_userkey'); return $collection; } /** * Get the list of contexts that contain user information for the specified user. * * This is currently just the user context. * * @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 { $sql = "SELECT ctx.id FROM {user_private_key} k JOIN {user} u ON k.userid = u.id JOIN {context} ctx ON ctx.instanceid = u.id AND ctx.contextlevel = :contextlevel WHERE k.userid = :userid AND k.script = :script"; $params = [ 'userid' => $userid, 'contextlevel' => CONTEXT_USER, 'script' => 'core_files', ]; $contextlist = new contextlist(); $contextlist->add_from_sql($sql, $params); return $contextlist; } /** * Get the list of users within a specific 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) { $context = $userlist->get_context(); if (!$context instanceof \context_user) { return; } \core_userkey\privacy\provider::get_user_contexts_with_script($userlist, $context, 'core_files'); } /** * 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) { // If the user has data, then only the CONTEXT_USER should be present so get the first context. $contexts = $contextlist->get_contexts(); if (count($contexts) == 0) { return; } // Sanity check that context is at the user context level, then get the userid. $context = reset($contexts); if ($context->contextlevel !== CONTEXT_USER) { return; } // Export associated userkeys. $subcontext = [ get_string('files'), ]; \core_userkey\privacy\provider::export_userkeys($context, $subcontext, 'core_files'); } /** * Delete all use data which matches the specified deletion_criteria. * * @param context $context A user context. */ public static function delete_data_for_all_users_in_context(\context $context) { // Sanity check that context is at the user context level, then get the userid. if ($context->contextlevel !== CONTEXT_USER) { return; } // Delete all the userkeys. \core_userkey\privacy\provider::delete_userkeys('core_files', $context->instanceid); } /** * 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) { $context = $userlist->get_context(); if ($context instanceof \context_user) { \core_userkey\privacy\provider::delete_userkeys('core_files', $context->instanceid); } } /** * 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) { // If the user has data, then only the user context should be present so get the first context. $contexts = $contextlist->get_contexts(); if (count($contexts) == 0) { return; } // Sanity check that context is at the user context level, then get the userid. $context = reset($contexts); if ($context->contextlevel !== CONTEXT_USER) { return; } // Delete all the userkeys for core_files.. \core_userkey\privacy\provider::delete_userkeys('core_files', $context->instanceid); } } PK b<�\R�l� � classes/archive_writer.phpnu �[��� <?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/>. /** * Abstraction of general file archives. * * @package core_files * @copyright 2020 Mark Nelson <mdjnelson@gmail.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_files; use core_files\local\archive_writer\file_writer_interface as file_writer_interface; use core_files\local\archive_writer\stream_writer_interface as stream_writer_interface; /** * Each file archive type must extend this class. * * @package core_files * @copyright 2020 Mark Nelson <mdjnelson@gmail.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ abstract class archive_writer { /** * The zip writer class. */ public const ZIP_WRITER = 'zip_writer'; /** * Returns the stream writer. * * @param string $filename * @param string $type * @return stream_writer_interface */ public static function get_stream_writer(string $filename, string $type): stream_writer_interface { $classname = self::get_classname_for_type($type); if (!is_a($classname, stream_writer_interface::class, true)) { throw new \InvalidArgumentException("{$type} does not support streaming"); } return $classname::stream_instance($filename); } /** * Returns the file writer. * * @param string $filepath * @param string $type * @return file_writer_interface */ public static function get_file_writer(string $filepath, string $type): file_writer_interface { $classname = self::get_classname_for_type($type); if (!is_a($classname, file_writer_interface::class, true)) { throw new \InvalidArgumentException("{$type} does not support writing to files"); } return $classname::file_instance($filepath); } /** * Sanitise the file path, removing any unsuitable characters. * * @param string $filepath * @return string */ public function sanitise_filepath(string $filepath): string { return clean_param($filepath, PARAM_PATH); } /** * Returns the class name for the type that was provided in get_file_writer(). * * @param string $type * @return string */ protected static function get_classname_for_type(string $type): string { return "core_files\local\archive_writer\\" . $type; } /** * The archive_writer Constructor. */ protected function __construct() { } /** * Adds a file from a file path. * * @param string $name The path of file in archive (including directory). * @param string $path The path to file on disk (note: paths should be encoded using * UNIX-style forward slashes -- e.g '/path/to/some/file'). */ abstract public function add_file_from_filepath(string $name, string $path): void; /** * Adds a file from a string. * * @param string $name The path of file in archive (including directory). * @param string $data The contents of file */ abstract public function add_file_from_string(string $name, string $data): void; /** * Adds a file from a stream. * * @param string $name The path of file in archive (including directory). * @param resource $stream The contents of file as a stream resource */ abstract public function add_file_from_stream(string $name, $stream): void; /** * Adds a stored_file to archive. * * @param string $name The path of file in archive (including directory). * @param \stored_file $file */ abstract public function add_file_from_stored_file(string $name, \stored_file $file): void; /** * Finish writing the zip footer. */ abstract public function finish(): void; } PK b<�\���7! 7! classes/converter.phpnu �[��� <?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/>. /** * Class for converting files between different file formats using unoconv. * * @package core_files * @copyright 2017 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_files; defined('MOODLE_INTERNAL') || die(); use stored_file; /** * Class for converting files between different formats using unoconv. * * @package core_files * @copyright 2017 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class converter { /** * Get a list of enabled plugins and classes. * * @return array List of enabled plugins */ protected function get_enabled_plugins() { $plugins = \core\plugininfo\fileconverter::get_enabled_plugins(); $pluginclasses = []; foreach ($plugins as $plugin) { $pluginclasses[$plugin] = \core\plugininfo\fileconverter::get_classname($plugin); } return $pluginclasses; } /** * Return the file_storage API. * * This allows for mocking of the file_storage API. * * @return \file_storage */ protected function get_file_storage() { return get_file_storage(); } /** * Start the conversion for a stored_file into a new format. * * @param stored_file $file The file to convert * @param string $format The desired target file format (file extension) * @param boolean $forcerefresh If true, the file will be converted every time (not cached). * @return conversion conversion object */ public function start_conversion(stored_file $file, $format, $forcerefresh = false) { $conversions = conversion::get_conversions_for_file($file, $format); if ($forcerefresh || count($conversions) > 1) { while ($conversion = array_shift($conversions)) { if ($conversion->get('id')) { $conversion->delete(); } } } if (empty($conversions)) { $conversion = new conversion(0, (object) [ 'sourcefileid' => $file->get_id(), 'targetformat' => $format, ]); $conversion->create(); } else { $conversion = array_shift($conversions); } if ($conversion->get('status') !== conversion::STATUS_COMPLETE) { $this->poll_conversion($conversion); } return $conversion; } /** * Poll for updates to the supplied conversion. * * @param conversion $conversion The conversion in progress * @return $this */ public function poll_conversion(conversion $conversion) { $format = $conversion->get('targetformat'); $file = $conversion->get_sourcefile(); if ($conversion->get('status') == conversion::STATUS_IN_PROGRESS) { // The current conversion is in progress. // Check for updates. if ($instance = $conversion->get_converter_instance()) { $instance->poll_conversion_status($conversion); } else { // Unable to fetch the converter instance. // Reset the status back to PENDING so that it may be picked up again. $conversion->set('status', conversion::STATUS_PENDING); } $conversion->update(); } // Refresh the status. $status = $conversion->get('status'); if ($status === conversion::STATUS_PENDING || $status === conversion::STATUS_FAILED) { // The current status is either pending or failed. // Attempt to pick up a new converter and convert the document. $from = pathinfo($file->get_filename(), PATHINFO_EXTENSION); $converters = $this->get_document_converter_classes($from, $format); $currentconverter = $this->get_next_converter($converters, $conversion->get('converter')); if (!$currentconverter) { // No more converters available. $conversion->set('status', conversion::STATUS_FAILED); $conversion->update(); return $this; } do { $conversion ->set('converter', $currentconverter) ->set('status', conversion::STATUS_IN_PROGRESS) ->update(); $instance = $conversion->get_converter_instance(); $instance->start_document_conversion($conversion); $failed = $conversion->get('status') === conversion::STATUS_FAILED; $currentconverter = $this->get_next_converter($converters, $currentconverter); } while ($failed && $currentconverter); $conversion->update(); } return $this; } /** * Fetch the next converter to try. * * @param array $converters The list of converters to try * @param string|null $currentconverter The converter currently in use * @return string|false Name of next converter if present */ protected function get_next_converter($converters, $currentconverter = null) { if ($currentconverter) { $keys = moodle_array_keys_filter($converters, $currentconverter); $key = $keys[0]; if (isset($converters[$key + 1])) { return $converters[$key + 1]; } else { return false; } } else if (!empty($converters)) { return $converters[0]; } else { return false; } } /** * Fetch the class for the preferred document converter. * * @param string $from The source target file (file extension) * @param string $to The desired target file format (file extension) * @return string The class for document conversion */ protected function get_document_converter_classes($from, $to) { $classes = []; $converters = $this->get_enabled_plugins(); foreach ($converters as $plugin => $classname) { if (!class_exists($classname)) { continue; } if (!$classname::are_requirements_met()) { continue; } if ($classname::supports($from, $to)) { $classes[] = $classname; } } return $classes; } /** * Check whether document conversion is supported for this file and target format. * * @param stored_file $file The file to convert * @param string $to The desired target file format (file extension) * @return bool Whether the target type can be converted */ public function can_convert_storedfile_to(stored_file $file, $to) { if ($file->is_directory()) { // Directories cannot be converted. return false; } if (!$file->get_filesize()) { // Empty files cannot be converted. return false; } $from = pathinfo($file->get_filename(), PATHINFO_EXTENSION); if (!$from) { // No file extension could be found. Unable to determine converter. return false; } return $this->can_convert_format_to($from, $to); } /** * Check whether document conversion is supported for this file and target format. * * @param string $from The source target file (file extension) * @param string $to The desired target file format (file extension) * @return bool Whether the target type can be converted */ public function can_convert_format_to($from, $to) { return !empty($this->get_document_converter_classes($from, $to)); } } PK b<�\螯P0 0 classes/conversion.phpnu �[��� <?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/>. /** * Classes for converting files between different file formats. * * @package core_files * @copyright 2017 Andrew Nicols <andrew@nicols.co.uk> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_files; defined('MOODLE_INTERNAL') || die(); use stored_file; /** * Class representing a conversion currently in progress. * * @package core_files * @copyright 2017 Andrew Nicols <andrew@nicols.co.uk> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class conversion extends \core\persistent { /** * Status value representing a conversion waiting to start. */ const STATUS_PENDING = 0; /** * Status value representing a conversion in progress. */ const STATUS_IN_PROGRESS = 1; /** * Status value representing a successful conversion. */ const STATUS_COMPLETE = 2; /** * Status value representing a failed conversion. */ const STATUS_FAILED = -1; /** * Table name for this persistent. */ const TABLE = 'file_conversion'; /** * Define properties. * * @return array */ protected static function define_properties() { return array( 'sourcefileid' => [ 'type' => PARAM_INT, ], 'targetformat' => [ 'type' => PARAM_ALPHANUMEXT, ], 'status' => [ 'type' => PARAM_INT, 'choices' => [ self::STATUS_PENDING, self::STATUS_IN_PROGRESS, self::STATUS_COMPLETE, self::STATUS_FAILED, ], 'default' => self::STATUS_PENDING, ], 'statusmessage' => [ 'type' => PARAM_RAW, 'null' => NULL_ALLOWED, 'default' => null, ], 'converter' => [ 'type' => PARAM_RAW, 'null' => NULL_ALLOWED, 'default' => null, ], 'destfileid' => [ 'type' => PARAM_INT, 'null' => NULL_ALLOWED, 'default' => null, ], 'data' => [ 'type' => PARAM_RAW, 'null' => NULL_ALLOWED, 'default' => null, ], ); } /** * Fetch all conversions relating to the specified file. * * Only conversions which have a valid file are returned. * * @param stored_file $file The source file being converted * @param string $format The targetforamt to filter to * @return conversion[] */ public static function get_conversions_for_file(stored_file $file, $format) { global $DB; $instances = []; // Conversion records are intended for tracking a conversion in progress or recently completed. // The record is removed periodically, but the destination file is not. // We need to fetch all conversion records which match the source file and target, and also all source and // destination files which do not have a conversion record. $sqlfields = self::get_sql_fields('c', 'conversion'); // Fetch actual conversions which relate to the specified source file, and have a matching conversion record, // and either have a valid destination file which still exists, or do not have a destination file at all. $sql = "SELECT {$sqlfields} FROM {" . self::TABLE . "} c JOIN {files} conversionsourcefile ON conversionsourcefile.id = c.sourcefileid LEFT JOIN {files} conversiondestfile ON conversiondestfile.id = c.destfileid WHERE conversionsourcefile.contenthash = :ccontenthash AND c.targetformat = :cformat AND (c.destfileid IS NULL OR conversiondestfile.id IS NOT NULL)"; // Fetch a empty conversion record for each source/destination combination that we find to match where the // destination file is in the correct filearea/filepath/filename combination to meet the requirements. // This ensures that existing conversions are used where possible, even if there is no 'conversion' record for // them. $sql .= " UNION ALL SELECT NULL AS conversionid, orphanedsourcefile.id AS conversionsourcefileid, :oformat AS conversiontargetformat, 2 AS conversionstatus, NULL AS conversionstatusmessage, NULL AS conversionconverter, orphaneddestfile.id AS conversiondestfileid, NULL AS conversiondata, 0 AS conversiontimecreated, 0 AS conversiontimemodified, 0 AS conversionusermodified FROM {files} orphanedsourcefile INNER JOIN {files} orphaneddestfile ON ( orphaneddestfile.filename = orphanedsourcefile.contenthash AND orphaneddestfile.component = 'core' AND orphaneddestfile.filearea = 'documentconversion' AND orphaneddestfile.filepath = :ofilepath ) LEFT JOIN {" . self::TABLE . "} orphanedconversion ON orphanedconversion.destfileid = orphaneddestfile.id WHERE orphanedconversion.id IS NULL AND orphanedsourcefile.id = :osourcefileid "; $records = $DB->get_records_sql($sql, [ 'ccontenthash' => $file->get_contenthash(), 'osourcefileid' => $file->get_id(), 'ofilepath' => "/{$format}/", 'cformat' => $format, 'oformat' => $format, ]); foreach ($records as $record) { $data = self::extract_record($record, 'conversion'); $newrecord = new static(0, $data); $instances[] = $newrecord; } return $instances; } /** * Remove all old conversion records. */ public static function remove_old_conversion_records() { global $DB; $DB->delete_records_select(self::TABLE, 'timemodified <= :weekagosecs', [ 'weekagosecs' => time() - WEEKSECS, ]); } /** * Remove orphan records. * * Records are considered orphans when their source file not longer exists. * In this scenario we do not want to keep the converted file any longer, * in particular to be compliant with privacy laws. */ public static function remove_orphan_records() { global $DB; $sql = " SELECT c.id FROM {" . self::TABLE . "} c LEFT JOIN {files} f ON f.id = c.sourcefileid WHERE f.id IS NULL"; $ids = $DB->get_fieldset_sql($sql, []); if (empty($ids)) { return; } list($insql, $inparams) = $DB->get_in_or_equal($ids, SQL_PARAMS_NAMED); $DB->delete_records_select(self::TABLE, "id $insql", $inparams); } /** * Set the source file id for the conversion. * * @param stored_file $file The file to convert * @return $this */ public function set_sourcefile(stored_file $file) { $this->raw_set('sourcefileid', $file->get_id()); return $this; } /** * Fetch the source file. * * @return stored_file|false The source file */ public function get_sourcefile() { $fs = get_file_storage(); return $fs->get_file_by_id($this->get('sourcefileid')); } /** * Set the destination file for this conversion. * * @param string $filepath The path to the converted file * @return $this */ public function store_destfile_from_path($filepath) { if ($record = $this->get_file_record()) { $fs = get_file_storage(); $existing = $fs->get_file( $record['contextid'], $record['component'], $record['filearea'], $record['itemid'], $record['filepath'], $record['filename'] ); if ($existing) { $existing->delete(); } $file = $fs->create_file_from_pathname($record, $filepath); $this->raw_set('destfileid', $file->get_id()); } return $this; } /** * Set the destination file for this conversion. * * @param string $content The content of the converted file * @return $this */ public function store_destfile_from_string($content) { if ($record = $this->get_file_record()) { $fs = get_file_storage(); $existing = $fs->get_file( $record['contextid'], $record['component'], $record['filearea'], $record['itemid'], $record['filepath'], $record['filename'] ); if ($existing) { $existing->delete(); } $file = $fs->create_file_from_string($record, $content); $this->raw_set('destfileid', $file->get_id()); } return $this; } /** * Get the destination file. * * @return stored_file|bool Destination file */ public function get_destfile() { $fs = get_file_storage(); return $fs->get_file_by_id($this->get('destfileid')); } /** * Helper to ensure that the returned status is always an int. * * @return int status */ protected function get_status() { return (int) $this->raw_get('status'); } /** * Get an instance of the current converter. * * @return converter_interface|false current converter instance */ public function get_converter_instance() { $currentconverter = $this->get('converter'); if ($currentconverter && class_exists($currentconverter)) { return new $currentconverter(); } else { return false; } } /** * Transform data into a storable format. * * @param \stdClass $data The data to be stored * @return $this */ protected function set_data($data) { $this->raw_set('data', json_encode($data)); return $this; } /** * Transform data into a storable format. * * @return \stdClass The stored data */ protected function get_data() { $data = $this->raw_get('data'); if (!empty($data)) { return json_decode($data); } return (object) []; } /** * Return the file record base for use in the files table. * * @return array|bool */ protected function get_file_record() { $file = $this->get_sourcefile(); if (!$file) { // If the source file was removed before we completed, we must return early. return false; } return [ 'contextid' => \context_system::instance()->id, 'component' => 'core', 'filearea' => 'documentconversion', 'itemid' => 0, 'filepath' => "/" . $this->get('targetformat') . "/", 'filename' => $file->get_contenthash(), ]; } } PK b<�\ӇQ� � * classes/reportbuilder/datasource/files.phpnu �[��� <?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/>. declare(strict_types=1); namespace core_files\reportbuilder\datasource; use core\reportbuilder\local\entities\context; use core_files\reportbuilder\local\entities\file; use core_reportbuilder\datasource; use core_reportbuilder\local\entities\user; use core_reportbuilder\local\filters\boolean_select; /** * Files datasource * * @package core_files * @copyright 2022 Paul Holden <paulh@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class files extends datasource { /** * Return user friendly name of the report source * * @return string */ public static function get_name(): string { return get_string('files'); } /** * Initialise report */ protected function initialise(): void { $fileentity = new file(); $filesalias = $fileentity->get_table_alias('files'); $this->set_main_table('files', $filesalias); $this->add_entity($fileentity); // Join the context entity. $contextentity = new context(); $contextalias = $contextentity->get_table_alias('context'); $this->add_entity($contextentity ->add_join("LEFT JOIN {context} {$contextalias} ON {$contextalias}.id = {$filesalias}.contextid") ); // Join the user entity. $userentity = new user(); $useralias = $userentity->get_table_alias('user'); $this->add_entity($userentity ->add_join("LEFT JOIN {user} {$useralias} ON {$useralias}.id = {$filesalias}.userid") ); // Add report elements from each of the entities we added to the report. $this->add_all_from_entities(); } /** * Return the columns that will be added to the report upon creation * * @return string[] */ public function get_default_columns(): array { return [ 'context:name', 'user:fullname', 'file:name', 'file:type', 'file:size', 'file:timecreated', ]; } /** * Return the column sorting that will be added to the report upon creation * * @return int[] */ public function get_default_column_sorting(): array { return [ 'context:name' => SORT_ASC, 'file:timecreated' => SORT_ASC, ]; } /** * Return the filters that will be added to the report upon creation * * @return string[] */ public function get_default_filters(): array { return [ 'file:size', 'file:timecreated', ]; } /** * Return the conditions that will be added to the report upon creation * * @return string[] */ public function get_default_conditions(): array { return ['file:directory']; } /** * Return the condition values that will be set for the report upon creation * * @return array */ public function get_default_condition_values(): array { return ['file:directory_operator' => boolean_select::NOT_CHECKED]; } } PK b<�\]y���>