Skip to content

Commit

Permalink
Merge branch 'MDL-32471-thumbnails' of git://github.com/mudrd8mz/moodle
Browse files Browse the repository at this point in the history
  • Loading branch information
stronk7 committed Apr 25, 2012
2 parents e69ac15 + b861b60 commit d7f84a2
Show file tree
Hide file tree
Showing 47 changed files with 575 additions and 182 deletions.
5 changes: 3 additions & 2 deletions blocks/html/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@
* @param string $filearea file area
* @param array $args extra arguments
* @param bool $forcedownload whether or not force download
* @param array $options additional options affecting the file serving
* @return bool
*/
function block_html_pluginfile($course, $birecord_or_cm, $context, $filearea, $args, $forcedownload) {
function block_html_pluginfile($course, $birecord_or_cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
global $SCRIPT;

if ($context->contextlevel != CONTEXT_BLOCK) {
Expand Down Expand Up @@ -64,7 +65,7 @@ function block_html_pluginfile($course, $birecord_or_cm, $context, $filearea, $a
}

session_get_instance()->write_close();
send_stored_file($file, 60*60, 0, $forcedownload);
send_stored_file($file, 60*60, 0, $forcedownload, $options);
}

/**
Expand Down
6 changes: 6 additions & 0 deletions blocks/upgrade.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
This files describes API changes in /blocks/* - activity modules,
information provided here is intended especially for developers.

=== 2.3 ===

required changes in code:
* block_xxx_pluginfile() is now given the 7th parameter (hopefully the last one) that
contains additional options for the file serving. The array should be re-passed
to send_stored_file().

=== 2.0 ===

Expand Down
107 changes: 71 additions & 36 deletions lib/filelib.php

Large diffs are not rendered by default.

126 changes: 126 additions & 0 deletions lib/filestorage/file_storage.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,113 @@ public function get_file_instance(stdClass $file_record) {
return new stored_file($this, $file_record, $this->filedir);
}

/**
* Returns an image file that represent the given stored file as a preview
*
* At the moment, only GIF, JPEG and PNG files are supported to have previews. In the
* future, the support for other mimetypes can be added, too (eg. generate an image
* preview of PDF, text documents etc).
*
* @param stored_file $file the file we want to preview
* @param string $mode preview mode, eg. 'thumb'
* @return stored_file|bool false if unable to create the preview, stored file otherwise
*/
public function get_file_preview(stored_file $file, $mode) {

$context = context_system::instance();
$path = '/' . trim($mode, '/') . '/';
$preview = $this->get_file($context->id, 'core', 'preview', 0, $path, $file->get_contenthash());

if (!$preview) {
$preview = $this->create_file_preview($file, $mode);
if (!$preview) {
return false;
}
}

return $preview;
}

/**
* Generates a preview image for the stored file
*
* @param stored_file $file the file we want to preview
* @param string $mode preview mode, eg. 'thumb'
* @return stored_file|bool the newly created preview file or false
*/
protected function create_file_preview(stored_file $file, $mode) {

$mimetype = $file->get_mimetype();

if ($mimetype === 'image/gif' or $mimetype === 'image/jpeg' or $mimetype === 'image/png') {
// make a preview of the image
$data = $this->create_imagefile_preview($file, $mode);

} else {
// unable to create the preview of this mimetype yet
return false;
}

if (empty($data)) {
return false;
}

// getimagesizefromstring() is available from PHP 5.4 but we need to support
// lower versions, so...
$tmproot = make_temp_directory('thumbnails');
$tmpfilepath = $tmproot.'/'.$file->get_contenthash().'_'.$mode;
file_put_contents($tmpfilepath, $data);
$imageinfo = getimagesize($tmpfilepath);
unlink($tmpfilepath);

$context = context_system::instance();

$record = array(
'contextid' => $context->id,
'component' => 'core',
'filearea' => 'preview',
'itemid' => 0,
'filepath' => '/' . trim($mode, '/') . '/',
'filename' => $file->get_contenthash(),
);

if ($imageinfo) {
$record['mimetype'] = $imageinfo['mime'];
}

return $this->create_file_from_string($record, $data);
}

/**
* Generates a preview for the stored image file
*
* @param stored_file $file the image we want to preview
* @param string $mode preview mode, eg. 'thumb'
* @return string|bool false if a problem occurs, the thumbnail image data otherwise
*/
protected function create_imagefile_preview(stored_file $file, $mode) {
global $CFG;
require_once($CFG->libdir.'/gdlib.php');

$tmproot = make_temp_directory('thumbnails');
$tmpfilepath = $tmproot.'/'.$file->get_contenthash();
$file->copy_content_to($tmpfilepath);

if ($mode === 'tinyicon') {
$data = generate_image_thumbnail($tmpfilepath, 16, 16);

} else if ($mode === 'thumb') {
$data = generate_image_thumbnail($tmpfilepath, 90, 90);

} else {
throw new file_exception('storedfileproblem', 'Invalid preview mode requested');
}

unlink($tmpfilepath);

return $data;
}

/**
* Fetch file using local file id.
*
Expand Down Expand Up @@ -1306,6 +1413,25 @@ public function cron() {
$rs->close();
mtrace('done.');

// remove orphaned preview files (that is files in the core preview filearea without
// the existing original file)
mtrace('Deleting orphaned preview files... ', '');
$sql = "SELECT p.*
FROM {files} p
LEFT JOIN {files} o ON (p.filename = o.contenthash)
WHERE p.contextid = ? AND p.component = 'core' AND p.filearea = 'preview' AND p.itemid = 0
AND o.id IS NULL";
$syscontext = context_system::instance();
$rs = $DB->get_recordset_sql($sql, array($syscontext->id));
foreach ($rs as $orphan) {
$file = $this->get_file_instance($orphan);
if (!$file->is_directory()) {
$file->delete();
}
}
$rs->close();
mtrace('done.');

// remove trash pool files once a day
// if you want to disable purging of trash put $CFG->fileslastcleanup=time(); into config.php
if (empty($CFG->fileslastcleanup) or $CFG->fileslastcleanup < time() - 60*60*24) {
Expand Down
80 changes: 80 additions & 0 deletions lib/filestorage/tests/file_storage_test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?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/>.

/**
* Unit tests for /lib/filestorage/file_storage.php
*
* @package core
* @category test
* @copyright 2012 David Mudrak <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

defined('MOODLE_INTERNAL') || die();

global $CFG;
require_once($CFG->libdir . '/filelib.php');

class filestoragelib_testcase extends advanced_testcase {

/**
* Local files can be added to the filepool
*/
public function test_create_file_from_pathname() {
global $CFG;

$this->resetAfterTest(false);

$filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
$syscontext = context_system::instance();
$filerecord = array(
'contextid' => $syscontext->id,
'component' => 'core',
'filearea' => 'unittest',
'itemid' => 0,
'filepath' => '/images/',
'filename' => 'testimage.jpg',
);

$fs = get_file_storage();
$fs->create_file_from_pathname($filerecord, $filepath);

$this->assertTrue($fs->file_exists($syscontext->id, 'core', 'unittest', 0, '/images/', 'testimage.jpg'));

return $fs->get_file($syscontext->id, 'core', 'unittest', 0, '/images/', 'testimage.jpg');
}

/**
* Local images can be added to the filepool and their preview can be obtained
*
* @depends test_create_file_from_pathname
*/
public function test_get_file_preview(stored_file $file) {
global $CFG;

$this->resetAfterTest(true);
$fs = get_file_storage();

$previewtinyicon = $fs->get_file_preview($file, 'tinyicon');
$this->assertInstanceOf('stored_file', $previewtinyicon);
$this->assertEquals('6b9864ae1536a8eeef54e097319175a8be12f07c', $previewtinyicon->get_filename());

$previewtinyicon = $fs->get_file_preview($file, 'thumb');
$this->assertInstanceOf('stored_file', $previewtinyicon);
$this->assertEquals('6b9864ae1536a8eeef54e097319175a8be12f07c', $previewtinyicon->get_filename());
}
}
Binary file added lib/filestorage/tests/fixtures/testimage.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit d7f84a2

Please sign in to comment.