Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

405 lines (384 sloc) 15.072 kb
<?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 plugin is used to access local files
*
* @since 2.0
* @package repository_local
* @copyright 2010 Dongsheng Cai {@link http://dongsheng.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once($CFG->dirroot . '/repository/lib.php');
/**
* repository_local class is used to browse moodle files
*
* @since 2.0
* @package repository_local
* @copyright 2009 Dongsheng Cai {@link http://dongsheng.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class repository_local extends repository {
/**
* local plugin doesn't require login, so list all files
* @return mixed
*/
public function print_login() {
return $this->get_listing();
}
/**
* Get file listing
*
* @param string $encodedpath
* @return mixed
*/
public function get_listing($encodedpath = '', $page = '') {
global $CFG, $USER, $OUTPUT;
$ret = array();
$ret['dynload'] = true;
$ret['nosearch'] = true;
$ret['nologin'] = true;
$list = array();
if (!empty($encodedpath)) {
$params = unserialize(base64_decode($encodedpath));
if (is_array($params)) {
$component = is_null($params['component']) ? NULL : clean_param($params['component'], PARAM_COMPONENT);
$filearea = is_null($params['filearea']) ? NULL : clean_param($params['filearea'], PARAM_AREA);
$itemid = is_null($params['itemid']) ? NULL : clean_param($params['itemid'], PARAM_INT);
$filepath = is_null($params['filepath']) ? NULL : clean_param($params['filepath'], PARAM_PATH);;
$filename = is_null($params['filename']) ? NULL : clean_param($params['filename'], PARAM_FILE);
$context = get_context_instance_by_id(clean_param($params['contextid'], PARAM_INT));
}
} else {
$itemid = null;
$filename = null;
$filearea = null;
$filepath = null;
$component = null;
if (!empty($this->context)) {
list($context, $course, $cm) = get_context_info_array($this->context->id);
if (is_object($course)) {
$context = get_context_instance(CONTEXT_COURSE, $course->id);
} else {
$context = get_system_context();
}
} else {
$context = get_system_context();
}
}
$browser = get_file_browser();
$list = array();
if ($fileinfo = $browser->get_file_info($context, $component, $filearea, $itemid, $filepath, $filename)) {
// build file tree
$element = repository_local_file::retrieve_file_info($fileinfo, $this);
$nonemptychildren = $element->get_non_empty_children();
foreach ($nonemptychildren as $child) {
$list[] = (array)$child->get_node();
}
} else {
// if file doesn't exist, build path nodes root of current context
$fileinfo = $browser->get_file_info($context, null, null, null, null, null);
}
// build path navigation
$ret['path'] = array();
$element = repository_local_file::retrieve_file_info($fileinfo, $this);
for ($level = $element; $level; $level = $level->get_parent()) {
if ($level == $element || !$level->can_skip()) {
array_unshift($ret['path'], $level->get_node_path());
}
}
$ret['list'] = array_filter($list, array($this, 'filter'));
return $ret;
}
/**
* Local file don't support to link to external links
*
* @return int
*/
public function supported_returntypes() {
return FILE_INTERNAL | FILE_REFERENCE;
}
/**
* Does this repository used to browse moodle files?
*
* @return boolean
*/
public function has_moodle_files() {
return true;
}
/**
* Return reference file life time
*
* @param string $ref
* @return int
*/
public function get_reference_file_lifetime($ref) {
// this should be realtime
return 0;
}
}
/**
* Class to cache some information about file
*
* This class is a wrapper to instances of file_info. It caches such information as
* parent and list of children. It also stores an array of already retrieved elements.
*
* It also implements more comprehensive algorithm for checking if folder is empty
* (taking into account the filtering of the files). To decrease number of levels
* we check if some subfolders can be skipped from the tree.
*
* As a result we display in Server files repository only non-empty folders and skip
* filearea folders if this is the only filearea in the module.
* For non-admin the course categories are not shown as well (courses are shown as a list)
*
* @package repository_local
* @copyright 2012 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class repository_local_file {
/** @var array stores already retrieved files */
private static $cachedfiles = array();
/** @var file_info Stores the original file */
public $fileinfo;
/** @var bool whether this file is directory */
private $isdir;
/** @var array caches retrieved children */
private $children = null;
/** @var array caches retrieved information whether this file is an empty directory */
protected $isempty = null;
/** @var repository link to the container repository (for filtering the results) */
private $repository;
/** @var repository_local_file link to parent directory */
protected $parent;
/** @var bool caches calculated information on whether this directory must be skipped in the tree */
private $skip = null;
/**
* Creates (or retrieves from cache) the repository_local_file object for $file_info
*
* @param file_info $fileinfo
* @param repository $repository
* @param repository_local_file $parent
* @return repository_local_file
*/
public static function retrieve_file_info(file_info $fileinfo, repository $repository, repository_local_file $parent = null) {
$encodedpath = base64_encode(serialize($fileinfo->get_params()));
if (!isset(self::$cachedfiles[$encodedpath])) {
self::$cachedfiles[$encodedpath] = new repository_local_file($fileinfo, $repository, $parent);
}
return self::$cachedfiles[$encodedpath];
}
/**
* Creates an object
*
* @param file_info $fileinfo
* @param repository $repository
* @param repository_local_file $parent
*/
private function __construct(file_info $fileinfo, repository $repository, repository_local_file $parent = null) {
$this->repository = $repository;
$this->fileinfo = $fileinfo;
$this->isdir = $fileinfo->is_directory();
if (!$this->isdir) {
$node = array('title' => $this->fileinfo->get_visible_name());
$this->isempty = !$repository->filter($node);
$this->skip = false;
}
}
/**
* Returns node for $ret['list']
*
* @return array
*/
public function get_node() {
global $OUTPUT;
$encodedpath = base64_encode(serialize($this->fileinfo->get_params()));
$node = array(
'title' => $this->fileinfo->get_visible_name(),
'datemodified' => $this->fileinfo->get_timemodified(),
'datecreated' => $this->fileinfo->get_timecreated()
);
if ($this->isdir) {
$node['path'] = $encodedpath;
$node['thumbnail'] = $OUTPUT->pix_url(file_folder_icon(90))->out(false);
$node['children'] = array();
} else {
$node['size'] = $this->fileinfo->get_filesize();
$node['author'] = $this->fileinfo->get_author();
$node['license'] = $this->fileinfo->get_license();
$node['isref'] = $this->fileinfo->is_external_file();
if ($this->fileinfo->get_status() == 666) {
$node['originalmissing'] = true;
}
$node['source'] = $encodedpath;
$node['thumbnail'] = $OUTPUT->pix_url(file_file_icon($this->fileinfo, 90))->out(false);
$node['icon'] = $OUTPUT->pix_url(file_file_icon($this->fileinfo, 24))->out(false);
if ($imageinfo = $this->fileinfo->get_imageinfo()) {
// what a beautiful picture, isn't it
$fileurl = new moodle_url($this->fileinfo->get_url());
$node['realthumbnail'] = $fileurl->out(false, array('preview' => 'thumb', 'oid' => $this->fileinfo->get_timemodified()));
$node['realicon'] = $fileurl->out(false, array('preview' => 'tinyicon', 'oid' => $this->fileinfo->get_timemodified()));
$node['image_width'] = $imageinfo['width'];
$node['image_height'] = $imageinfo['height'];
}
}
return $node;
}
/**
* Returns node for $ret['path']
*
* @return array
*/
public function get_node_path() {
$encodedpath = base64_encode(serialize($this->fileinfo->get_params()));
return array(
'path' => $encodedpath,
'name' => $this->fileinfo->get_visible_name()
);
}
/**
* Checks if this is a directory
*
* @return bool
*/
public function is_dir() {
return $this->isdir;
}
/**
* Returns children of this element
*
* @return array
*/
public function get_children() {
if (!$this->isdir) {
return array();
}
if ($this->children === null) {
$this->children = array();
$children = $this->fileinfo->get_children();
for ($i=0; $i<count($children); $i++) {
$this->children[] = self::retrieve_file_info($children[$i], $this->repository, $this);
}
}
return $this->children;
}
/**
* Checks if this folder is empty (contains no non-empty children)
*
* @return bool
*/
public function is_empty() {
if ($this->isempty === null) {
$this->isempty = true;
if (!$this->fileinfo->is_empty_area()) {
// even if is_empty_area() returns false, element still may be empty
$children = $this->get_children();
if (!empty($children)) {
// 1. Let's look at already retrieved children
foreach ($children as $childnode) {
if ($childnode->isempty === false) {
// we already calculated isempty for a child, and it is not empty
$this->isempty = false;
break;
}
}
if ($this->isempty) {
// 2. now we know that this directory contains children that are either empty or we don't know
foreach ($children as $childnode) {
if (!$childnode->is_empty()) {
$this->isempty = false;
break;
}
}
}
}
}
}
return $this->isempty;
}
/**
* Returns the parent element
*
* @return repository_local_file
*/
public function get_parent() {
if ($this->parent === null) {
if ($parent = $this->fileinfo->get_parent()) {
$this->parent = self::retrieve_file_info($parent, $this->repository);
} else {
$this->parent = false;
}
}
return $this->parent;
}
/**
* Wether this folder may be skipped in tree view
*
* @return bool
*/
public function can_skip() {
global $CFG;
if ($this->skip === null) {
$this->skip = false;
if ($this->fileinfo instanceof file_info_stored) {
$params = $this->fileinfo->get_params();
if (strlen($params['filearea']) && $params['filepath'] == '/' && $params['filename'] == '.') {
// This is a filearea inside an activity, it can be skipped if it has no non-empty siblings
if ($parent = $this->get_parent()) {
$siblings = $parent->get_children();
$countnonempty = 0;
foreach ($siblings as $sibling) {
if (!$sibling->is_empty()) {
$countnonempty++;
if ($countnonempty > 1) {
break;
}
}
}
if ($countnonempty <= 1) {
$this->skip = true;
}
}
}
} else if ($this->fileinfo instanceof file_info_context_coursecat) {
// This is a course category. For non-admins we do not display categories
$this->skip = empty($CFG->navshowmycoursecategories) &&
!has_capability('moodle/course:update', get_context_instance(CONTEXT_SYSTEM));
}
}
return $this->skip;
}
/**
* Returns array of children who have any elmenets
*
* If a subfolder can be skipped - list children of subfolder instead
* (recursive function)
*
* @return array
*/
public function get_non_empty_children() {
$children = $this->get_children();
$nonemptychildren = array();
foreach ($children as $child) {
if (!$child->is_empty()) {
if ($child->can_skip()) {
$nonemptychildren = array_merge($nonemptychildren, $child->get_non_empty_children());
} else {
$nonemptychildren[] = $child;
}
}
}
return $nonemptychildren;
}
}
Jump to Line
Something went wrong with that request. Please try again.