#2851 portfolio integration
parent
db83ff5706
commit
bffe3f6015
@ -1 +0,0 @@ |
||||
<?php |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,154 @@ |
||||
<?php |
||||
|
||||
Use Model\Document; |
||||
Use Model\Course; |
||||
|
||||
/** |
||||
* Return either |
||||
* |
||||
* - one document |
||||
* - several documents (file and/or folders) zipped together |
||||
* |
||||
* Used to transfer files to another application through http. |
||||
* |
||||
* Script parameters: |
||||
* |
||||
* - id id(s) of the document id=1 or id=1,2,4 |
||||
* - cidReq course code |
||||
* |
||||
* Note this script enables key authentication so access with a key token is possible. |
||||
* |
||||
* @package chamilo.document |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
require_once __DIR__ . '/../inc/autoload.inc.php'; |
||||
KeyAuth::enable(); |
||||
|
||||
require_once __DIR__ . '/../inc/global.inc.php'; |
||||
|
||||
$has_access = api_protect_course_script(); |
||||
if (!$has_access) { |
||||
exit; |
||||
} |
||||
|
||||
session_cache_limiter('none'); |
||||
|
||||
$ids = Request::get('id', ''); |
||||
$ids = $ids ? explode(',', $ids) : array(); |
||||
|
||||
$course = Course::current(); |
||||
|
||||
/** |
||||
* No files requested. We make sure we return 404 error to tell the client |
||||
* that the call failed. |
||||
*/ |
||||
if (count($ids) == 0 || empty($course)) { |
||||
Response::not_found(); |
||||
} |
||||
|
||||
/** |
||||
* One file requested. In this case we return the file itself. |
||||
*/ |
||||
if (count($ids) == 1) { |
||||
$id = reset($ids); |
||||
$doc = Document::get_by_id($course, $id); |
||||
if (empty($doc)) { |
||||
Response::not_found(); |
||||
} |
||||
|
||||
if ($doc->is_file()) { |
||||
$has_access = $doc->is_accessible(); |
||||
if (!$has_access) { |
||||
Response::not_found(); |
||||
} |
||||
|
||||
event_download(Uri::here()); |
||||
DocumentManager::file_send_for_download($doc); |
||||
exit; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Several files requested. In this case we zip them together. |
||||
*/ |
||||
$files = array(); |
||||
$folders = array(); |
||||
foreach ($ids as $id) { |
||||
$doc = Document::get_by_id($course, $id); |
||||
if (!$doc->is_accessible()) { |
||||
break; |
||||
} |
||||
if ($doc->is_file()) { |
||||
$files[] = $doc; |
||||
} |
||||
if ($doc->is_folder()) { |
||||
$folders[] = $doc; |
||||
} |
||||
} |
||||
|
||||
$requested_folders = $folders; |
||||
|
||||
/** |
||||
* Note that if a parent folder is hidden children should not be accesible |
||||
* even if they are visible. It is therefore not sufficient to check document |
||||
* visibility. |
||||
*/ |
||||
while ($folders) { |
||||
$items = $folders; |
||||
$folders = array(); |
||||
foreach ($items as $item) { |
||||
$children = $item->get_children(); |
||||
foreach ($children as $child) { |
||||
if (!$child->is_accessible()) { |
||||
break; |
||||
} |
||||
if ($child->is_file()) { |
||||
$files[] = $child; |
||||
} |
||||
if ($child->is_folder()) { |
||||
$folders[] = $child; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
$folders = $requested_folders; |
||||
|
||||
/** |
||||
* Requested files may not be accessible. |
||||
*/ |
||||
if (count($files) == 0) { |
||||
Response::not_found(); |
||||
} |
||||
|
||||
$root_dir = ''; |
||||
$items = array_merge($folders, $files); |
||||
foreach ($items as $item) { |
||||
$path = $item->get_absolute_path(); |
||||
$path = realpath($path); |
||||
$dir = dirname($path); |
||||
|
||||
if (empty($root_dir) || strlen($root_dir) > strlen($dir)) { |
||||
$root_dir = $dir; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Zip files together. |
||||
*/ |
||||
$temp_zip_path = Chamilo::temp_file('zip'); |
||||
$zip_folder = new PclZip($temp_zip_path); |
||||
foreach ($files as $file) { |
||||
if (empty($root_dir)) { |
||||
$root_dir = dirname($file); |
||||
} |
||||
$file = (string) $file; |
||||
$zip_folder->add($file, PCLZIP_OPT_REMOVE_PATH, $root_dir); |
||||
} |
||||
|
||||
/** |
||||
* Send file for download |
||||
*/ |
||||
event_download(Uri::here()); |
||||
DocumentManager::file_send_for_download($temp_zip_path, false, get_lang('Documents') . '.zip'); |
After Width: | Height: | Size: 1.1 KiB |
@ -0,0 +1,185 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* An access token. Can be passed between applications to grant access. |
||||
* |
||||
* The token aggregate several values together (key id, api key, user id). This |
||||
* is useful to pass a single value between application and avoid passing |
||||
* each value as a separate parameter. |
||||
* |
||||
* Note that values are aggregated but not crypted. An external application could |
||||
* have access to individual components. |
||||
* |
||||
* @see /main/auth/key_auth.class.php |
||||
* @see table user_api_key |
||||
* |
||||
* Usage: |
||||
* |
||||
* Validate token: |
||||
* |
||||
* $data = Request::get('access_token'); |
||||
* $token = AccessToken::parse($data); |
||||
* $token->is_valid(); |
||||
* |
||||
* Pass token |
||||
* |
||||
* $token = new AccessToken(1, 1, '+*ç*%ç*ç'); |
||||
* $url = '.....?access_token=' . $token; |
||||
* |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
class AccessToken |
||||
{ |
||||
|
||||
static function empty_token() |
||||
{ |
||||
static $result = null; |
||||
if (empty($result)) { |
||||
$result = new self(0, 0, ''); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param type $string |
||||
* @return AccessToken |
||||
*/ |
||||
static function parse($string) |
||||
{ |
||||
if (empty($string)) { |
||||
return self::empty_token(); |
||||
} |
||||
|
||||
$data = base64_decode($string); |
||||
$data = explode('/', $data); |
||||
|
||||
if (count($data) != 3) { |
||||
return self::empty_token(); |
||||
} |
||||
|
||||
$id = $data[0]; |
||||
$user_id = $data[1]; |
||||
$key = $data[2]; |
||||
return new self($id, $user_id, $key); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param int $id |
||||
* @param int $user_id |
||||
* @param string $key |
||||
* @return AccessToken |
||||
*/ |
||||
static function create($id, $user_id, $key) |
||||
{ |
||||
$is_valid = !empty($id) && !empty($user_id) && !empty($key); |
||||
return $is_valid ? new self($id, $user_id, $key) : self::empty_token(); |
||||
} |
||||
|
||||
protected $id = 0; |
||||
protected $user_id = 0; |
||||
protected $key = ''; |
||||
|
||||
/** |
||||
* |
||||
* @param int $id |
||||
* @param int $user_id |
||||
* @param string $key |
||||
*/ |
||||
function __construct($id, $user_id, $key) |
||||
{ |
||||
$this->id = $id; |
||||
$this->user_id = $user_id; |
||||
$this->key = $key; |
||||
} |
||||
|
||||
/** |
||||
* The user_api_key id. |
||||
* |
||||
* @return int |
||||
*/ |
||||
function get_id() |
||||
{ |
||||
return $this->id; |
||||
} |
||||
|
||||
/** |
||||
* User id. |
||||
* |
||||
* @return string |
||||
*/ |
||||
function get_user_id() |
||||
{ |
||||
return $this->user_id; |
||||
} |
||||
|
||||
/** |
||||
* User api key. |
||||
* |
||||
* @return string |
||||
*/ |
||||
function get_key() |
||||
{ |
||||
return $this->key; |
||||
} |
||||
|
||||
/** |
||||
* True if the token is an empty token. I.e. a no access token. |
||||
* |
||||
* @return bool |
||||
*/ |
||||
function is_empty() |
||||
{ |
||||
return empty($this->id) || empty($this->user_id) || empty($this->key); |
||||
} |
||||
|
||||
/** |
||||
* Validate token against the database. Returns true if token is valid, |
||||
* false otherwise. |
||||
* |
||||
* @return boolean |
||||
*/ |
||||
function is_valid() |
||||
{ |
||||
if ($this->is_empty()) { |
||||
return false; |
||||
} |
||||
$key = UserApiKeyManager::get_by_id($this->id); |
||||
if (empty($key)) { |
||||
return false; |
||||
} |
||||
|
||||
if ($key['api_key'] != $this->key) { |
||||
return false; |
||||
} |
||||
|
||||
if ($key['user_id'] != $this->user_id) { |
||||
return false; |
||||
} |
||||
|
||||
$time = time(); |
||||
$validity_start_date = $key['validity_start_date'] ? strtotime($key['validity_start_date']) : $time; |
||||
$validity_end_date = $key['validity_end_date'] ? strtotime($key['validity_end_date']) : $time + 100000; |
||||
return $validity_start_date <= $time && $time <= $validity_end_date; |
||||
} |
||||
|
||||
/** |
||||
* Returns a string representation of the token that can be passed in a url or a form. |
||||
* The string representation can be parsed by calling AccessToken::parse(); |
||||
* |
||||
* @return string |
||||
*/ |
||||
function __toString() |
||||
{ |
||||
$data[] = $this->id; |
||||
$data[] = $this->user_id; |
||||
$data[] = $this->key; |
||||
|
||||
$result = implode('/', $data); |
||||
$result = base64_encode($result); |
||||
return $result; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,145 @@ |
||||
<?php |
||||
|
||||
namespace Model; |
||||
|
||||
use Database; |
||||
use ResultSet; |
||||
|
||||
/** |
||||
* Description of course |
||||
* |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
class Course |
||||
{ |
||||
|
||||
/** |
||||
* |
||||
* @param string $where |
||||
* @return \ResultSet |
||||
*/ |
||||
public static function query($where) |
||||
{ |
||||
$table = Database::get_main_table(TABLE_MAIN_COURSE); |
||||
$sql = "SELECT * FROM $table "; |
||||
$sql .= $where ? "WHERE $where" : ''; |
||||
$result = new ResultSet($sql); |
||||
return $result->return_type(__CLASS__); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param string $code |
||||
* @return \Model\Course|null |
||||
*/ |
||||
public static function get_by_code($code) |
||||
{ |
||||
$current = self::current(); |
||||
if ($current && $current->get_code() == $code) { |
||||
return $current; |
||||
} |
||||
return self::query("code = '$code'")->first(); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param int $id |
||||
* @return \Model\Course|null |
||||
*/ |
||||
public static function get_by_id($id) |
||||
{ |
||||
$id = (int) $id; |
||||
$current = self::current(); |
||||
if ($current && $current->get_id() == $id) { |
||||
return $current; |
||||
} |
||||
return self::query("id = $id")->first(); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @return \Model\Course|null |
||||
*/ |
||||
public static function current() |
||||
{ |
||||
global $_course; |
||||
/** |
||||
* Note that $_course = -1 when not set. |
||||
*/ |
||||
if (empty($_course) || !is_array($_course)) { |
||||
return null; |
||||
} |
||||
|
||||
static $result = null; |
||||
if (empty($result)) { |
||||
$id = $_course['real_id']; |
||||
$result = self::query("id = $id")->first(); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
protected $id = 0; |
||||
protected $code = 0; |
||||
protected $directory = ''; |
||||
protected $show_score = ''; |
||||
|
||||
public function __construct($data) |
||||
{ |
||||
$data = (object) $data; |
||||
$this->id = $data->id; |
||||
$this->code = $data->code; |
||||
$this->directory = $data->directory; |
||||
$this->show_score = $data->show_score; |
||||
} |
||||
|
||||
public function get_id() |
||||
{ |
||||
return $this->id; |
||||
} |
||||
|
||||
public function set_id($value) |
||||
{ |
||||
$this->id = (int) $value; |
||||
} |
||||
|
||||
public function get_code() |
||||
{ |
||||
return $this->code; |
||||
} |
||||
|
||||
public function set_code($value) |
||||
{ |
||||
$this->code = (int) $value; |
||||
} |
||||
|
||||
public function get_directory() |
||||
{ |
||||
return $this->directory; |
||||
} |
||||
|
||||
public function set_directory($value) |
||||
{ |
||||
$this->directory = (int) $value; |
||||
} |
||||
|
||||
public function get_show_score() |
||||
{ |
||||
return $this->show_score; |
||||
} |
||||
|
||||
public function set_show_score($value) |
||||
{ |
||||
$this->show_score = (int) $value; |
||||
} |
||||
|
||||
public function get_path() |
||||
{ |
||||
$dir = $this->directory; |
||||
if (empty($dir)) { |
||||
return ''; |
||||
} |
||||
return api_get_path(SYS_COURSE_PATH) . $dir . '/'; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,302 @@ |
||||
<?php |
||||
|
||||
namespace Model; |
||||
|
||||
use Database; |
||||
use ResultSet; |
||||
|
||||
/** |
||||
* Represent a database "document" object - i.e. a file or a folder. |
||||
* |
||||
* Note: |
||||
* |
||||
* Each database column is mapped to a property. |
||||
* |
||||
* The item_property table is available through its own property but is loaded |
||||
* alongside document data. |
||||
* |
||||
* Some db query functions exists in this class and would need to be adapted |
||||
* to Symphony once it is moved to production. Yet the object structure should |
||||
* stay. |
||||
* |
||||
* @see \Model\ItemProperty |
||||
* @see table c_document |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
class Document |
||||
{ |
||||
|
||||
/** |
||||
* |
||||
* @param string $where |
||||
* @return \ResultSet |
||||
*/ |
||||
public static function query($where) |
||||
{ |
||||
$table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY); |
||||
$table_document = Database::get_course_table(TABLE_DOCUMENT); |
||||
$tool = TOOL_DOCUMENT; |
||||
|
||||
$sql = "SELECT doc.*, |
||||
prop.id AS property_id, |
||||
prop.tool, |
||||
prop.insert_user_id, |
||||
prop.insert_date, |
||||
prop.lastedit_date, |
||||
prop.ref, |
||||
prop.lastedit_type, |
||||
prop.lastedit_user_id, |
||||
prop.to_group_id, |
||||
prop.to_user_id, |
||||
prop.visibility, |
||||
prop.start_visible, |
||||
prop.end_visible, |
||||
prop.id_session |
||||
FROM |
||||
$table_document AS doc, |
||||
$table_item_property AS prop |
||||
WHERE |
||||
(doc.id = prop.ref AND |
||||
doc.c_id = prop.c_id AND |
||||
prop.tool = '$tool')"; |
||||
|
||||
$sql .= $where ? "AND ($where)" : ''; |
||||
$result = new ResultSet($sql); |
||||
return $result->return_type(__CLASS__); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param int|Course $c_id |
||||
* @param int $id |
||||
* @return \Model\Document |
||||
*/ |
||||
public static function get_by_id($c_id, $id) |
||||
{ |
||||
$c_id = is_object($c_id) ? $c_id->get_id() : (int) $c_id; |
||||
return self::query("doc.c_id = $c_id AND doc.id = $id")->first(); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param int|Course $c_id |
||||
* @param int $id |
||||
* @return \Model\Document |
||||
*/ |
||||
public static function get_by_path($c_id, $path) |
||||
{ |
||||
$c_id = is_object($c_id) ? $c_id->get_id() : (int) $c_id; |
||||
return self::query("doc.c_id = $c_id AND doc.path = '$path'")->first(); |
||||
} |
||||
|
||||
protected $c_id = 0; |
||||
protected $id = 0; |
||||
protected $path = ''; |
||||
protected $comment = ''; |
||||
protected $title = ''; |
||||
protected $filetype = ''; |
||||
protected $size = 0; |
||||
protected $readonly = false; |
||||
protected $session_id = 0; |
||||
protected $course = null; |
||||
protected $item_property = null; |
||||
|
||||
public function __construct($data) |
||||
{ |
||||
$data = (object) $data; |
||||
$this->c_id = (int) $data->c_id; |
||||
$this->id = (int) $data->id; |
||||
$this->path = $data->path; |
||||
$this->comment = $data->comment; |
||||
$this->title = $data->title; |
||||
$this->filetype = $data->filetype; |
||||
$this->size = (int) $data->size; |
||||
$this->readonly = (bool) $data->readonly; |
||||
$this->session_id = (int) $data->session_id; |
||||
|
||||
$this->course = null; |
||||
|
||||
if (isset($data->property_id)) { |
||||
$property = (array) $data; |
||||
$property = (object) $property; |
||||
$property->id = $property->property_id; |
||||
$this->item_property = ItemProperty::create($property); |
||||
} else { |
||||
$this->item_property = null; |
||||
} |
||||
} |
||||
|
||||
public function get_c_id() |
||||
{ |
||||
return $this->c_id; |
||||
} |
||||
|
||||
public function set_c_id($value) |
||||
{ |
||||
$this->c_id = (int) $value; |
||||
$this->course = null; |
||||
$this->item_property = null; |
||||
} |
||||
|
||||
public function get_id() |
||||
{ |
||||
return $this->id; |
||||
} |
||||
|
||||
public function set_id($value) |
||||
{ |
||||
$this->id = (int) $value; |
||||
$this->item_property = null; |
||||
} |
||||
|
||||
public function get_path() |
||||
{ |
||||
return $this->path; |
||||
} |
||||
|
||||
public function set_path($value) |
||||
{ |
||||
$this->path = $value; |
||||
} |
||||
|
||||
public function get_comment() |
||||
{ |
||||
return $this->comment; |
||||
} |
||||
|
||||
public function set_comment($value) |
||||
{ |
||||
$this->comment = $value; |
||||
} |
||||
|
||||
public function get_title() |
||||
{ |
||||
return $this->title; |
||||
} |
||||
|
||||
public function set_title($value) |
||||
{ |
||||
$this->title = $value; |
||||
} |
||||
|
||||
public function get_filetype() |
||||
{ |
||||
return $this->filetype; |
||||
} |
||||
|
||||
public function set_filetype($value) |
||||
{ |
||||
$this->filetype = $value; |
||||
} |
||||
|
||||
public function get_size() |
||||
{ |
||||
return $this->size; |
||||
} |
||||
|
||||
public function set_size($value) |
||||
{ |
||||
$this->size = (int) $value; |
||||
} |
||||
|
||||
public function get_readonly() |
||||
{ |
||||
return $this->readonly; |
||||
} |
||||
|
||||
public function set_readonly($value) |
||||
{ |
||||
$this->readonly = (bool) $value; |
||||
} |
||||
|
||||
public function get_session_id() |
||||
{ |
||||
return $this->session_id; |
||||
} |
||||
|
||||
public function set_session_id($value) |
||||
{ |
||||
$this->session_id = (int) $value; |
||||
} |
||||
|
||||
public function is_folder() |
||||
{ |
||||
return $this->filetype == 'folder'; |
||||
} |
||||
|
||||
public function is_file() |
||||
{ |
||||
return $this->filetype == 'file'; |
||||
} |
||||
|
||||
public function is_visible() |
||||
{ |
||||
$this->get_item_property()->get_visibility() == 1; |
||||
} |
||||
|
||||
public function is_accessible() |
||||
{ |
||||
return api_is_allowed_to_edit() || $this->is_visible(); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @return \Model\Course |
||||
*/ |
||||
public function get_course() |
||||
{ |
||||
if ($this->course && $this->course->get_id() == $this->c_id) { |
||||
return $this->course; |
||||
} |
||||
|
||||
$this->course = Course::get_by_id($this->c_id); |
||||
return $this->course; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @return \Model\ItemProperty |
||||
*/ |
||||
public function get_item_property() |
||||
{ |
||||
if ($this->item_property && $this->item_property->get_c_id() == $this->c_id && $this->item_property->get_ref() == $this->id) { |
||||
return $this->item_property; |
||||
} |
||||
|
||||
$this->item_property = ItemProperty::get_by_ref($this->id, TOOL_DOCUMENT); |
||||
return $this->item_property; |
||||
} |
||||
|
||||
public function get_absolute_path() |
||||
{ |
||||
$course = $this->get_course(); |
||||
return $course->get_path() . 'document' . $this->path; |
||||
} |
||||
|
||||
public function __toString() |
||||
{ |
||||
return $this->get_absolute_path(); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param bool $all |
||||
* @return ResultSet|array |
||||
*/ |
||||
public function get_children($all = false) |
||||
{ |
||||
if (!$this->is_folder()) { |
||||
return array(); |
||||
} |
||||
$path = $this->path; |
||||
$c_id = $this->c_id; |
||||
if ($this->all) { |
||||
$where = "doc.c_id = $c_id AND doc.path LIKE '$path/%'"; |
||||
} else { |
||||
$where = "doc.c_id = $c_id AND doc.path LIKE '$path/%' AND doc.path NOT LIKE '$path/%/%'"; |
||||
} |
||||
return self::query($where); |
||||
} |
||||
|
||||
} |
@ -1,32 +0,0 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* Header utility functions. |
||||
* |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
class Header |
||||
{ |
||||
|
||||
public static function content_type($mime_type, $charset = '') |
||||
{ |
||||
if (empty($mime_type)) |
||||
{ |
||||
return; |
||||
} |
||||
$type = $charset ? "$mime_type;charset=$charset" : $mime_type; |
||||
header('Content-type: ' . $type); |
||||
} |
||||
|
||||
public static function content_type_xml() |
||||
{ |
||||
header('Content-type: text/xml'); |
||||
} |
||||
|
||||
public static function content_type_javascript() |
||||
{ |
||||
header('Content-type: application/javascript'); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,251 @@ |
||||
<?php |
||||
|
||||
namespace Model; |
||||
use ResultSet; |
||||
|
||||
use Database; |
||||
|
||||
/** |
||||
* Represent a database "item_property" object - i.e. common properties for tool |
||||
* objects: created date, modified date, etc. |
||||
* |
||||
* Note: |
||||
* |
||||
* Each database column is mapped to a property. |
||||
* |
||||
* |
||||
* Some db query functions exists in this class and would need to be adapted |
||||
* to Sympony once it is moved to production. Yet the object structure should |
||||
* stay. |
||||
* |
||||
* @see \Model\ItemProperty |
||||
* @see table c_item_property |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
class ItemProperty |
||||
{ |
||||
|
||||
/** |
||||
* |
||||
* @param string $where |
||||
* @return \ResultSet |
||||
*/ |
||||
public static function query($where) |
||||
{ |
||||
$table = Database::get_course_table(TABLE_ITEM_PROPERTY); |
||||
$sql = "SELECT * FROM $table "; |
||||
$sql .= $where ? "WHERE $where" : ''; |
||||
$result = new ResultSet($sql); |
||||
return $result->return_type(__CLASS__); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param id $ref |
||||
* @param string $tool |
||||
* @return \Model\ItemProperty |
||||
*/ |
||||
public static function get_by_ref($ref, $tool) |
||||
{ |
||||
return self::query("ref=$ref AND tool = '$tool'")->first(); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param array|object $data |
||||
* @return \Model\ItemProperty |
||||
*/ |
||||
static function create($data) |
||||
{ |
||||
return new self($data); |
||||
} |
||||
|
||||
protected $c_id = 0; |
||||
protected $id = 0; |
||||
protected $tool = ''; |
||||
protected $insert_user_id = 0; |
||||
protected $insert_date = 0; |
||||
protected $lastedit_date = 0; |
||||
protected $ref = ''; |
||||
protected $lastedit_type = ''; |
||||
protected $lastedit_user_id = 0; |
||||
protected $to_group_id = null; |
||||
protected $to_user_id = null; |
||||
protected $visibility = 1; |
||||
protected $start_visible = 0; |
||||
protected $end_visible = 0; |
||||
protected $id_session = 0; |
||||
|
||||
public function __construct($data) |
||||
{ |
||||
$data = (object) $data; |
||||
$this->c_id = $data->c_id; |
||||
$this->id = $data->id; |
||||
$this->tool = $data->tool; |
||||
$this->insert_user_id = $data->insert_user_id; |
||||
$this->insert_date = $data->insert_date; |
||||
$this->lastedit_date = $data->lastedit_date; |
||||
$this->lastedit_date = $data->lastedit_date; |
||||
$this->ref = $data->ref; |
||||
$this->lastedit_type = $data->lastedit_type; |
||||
$this->lastedit_user_id = $data->lastedit_user_id; |
||||
$this->to_group_id = $data->to_group_id; |
||||
$this->to_user_id = $data->to_user_id; |
||||
$this->visibility = $data->visibility; |
||||
$this->start_visible = $data->start_visible; |
||||
$this->end_visible = $data->end_visible; |
||||
$this->id_session = $data->id_session; |
||||
} |
||||
|
||||
public function get_c_id() |
||||
{ |
||||
return $this->c_id; |
||||
} |
||||
|
||||
public function set_c_id($value) |
||||
{ |
||||
$this->c_id = (int) $value; |
||||
} |
||||
|
||||
public function get_id() |
||||
{ |
||||
return $this->id; |
||||
} |
||||
|
||||
public function set_id($value) |
||||
{ |
||||
$this->id = (int) $value; |
||||
} |
||||
|
||||
public function get_tool() |
||||
{ |
||||
return $this->tool; |
||||
} |
||||
|
||||
public function set_tool($value) |
||||
{ |
||||
$this->tool = $value; |
||||
} |
||||
|
||||
public function get_insert_user_id() |
||||
{ |
||||
return $this->insert_user_id; |
||||
} |
||||
|
||||
public function set_insert_user_id($value) |
||||
{ |
||||
$this->insert_user_id = $value; |
||||
} |
||||
|
||||
public function get_insert_date() |
||||
{ |
||||
return $this->insert_date; |
||||
} |
||||
|
||||
public function set_insert_date($value) |
||||
{ |
||||
$this->insert_date = $value; |
||||
} |
||||
|
||||
public function get_lastedit_date() |
||||
{ |
||||
return $this->lastedit_date; |
||||
} |
||||
|
||||
public function set_lastedit_date($value) |
||||
{ |
||||
$this->lastedit_date = $value; |
||||
} |
||||
|
||||
public function get_ref() |
||||
{ |
||||
return $this->ref; |
||||
} |
||||
|
||||
public function set_ref($value) |
||||
{ |
||||
$this->ref = $value; |
||||
} |
||||
|
||||
public function get_lastedit_type() |
||||
{ |
||||
return $this->lastedit_type; |
||||
} |
||||
|
||||
public function set_lastedit_type($value) |
||||
{ |
||||
$this->lastedit_type = $value; |
||||
} |
||||
|
||||
public function get_lastedit_user_id() |
||||
{ |
||||
return $this->lastedit_user_id; |
||||
} |
||||
|
||||
public function set_lastedit_user_id($value) |
||||
{ |
||||
$this->lastedit_user_id = $value; |
||||
} |
||||
|
||||
public function get_to_group_id() |
||||
{ |
||||
return $this->to_group_id; |
||||
} |
||||
|
||||
public function set_to_group_id($value) |
||||
{ |
||||
$this->to_group_id = $value; |
||||
} |
||||
|
||||
public function get_to_user_id() |
||||
{ |
||||
return $this->to_user_id; |
||||
} |
||||
|
||||
public function set_to_user_id($value) |
||||
{ |
||||
$this->to_user_id = $value; |
||||
} |
||||
|
||||
public function get_visibility() |
||||
{ |
||||
return $this->visibility; |
||||
} |
||||
|
||||
public function set_visibility($value) |
||||
{ |
||||
$this->visibility = $value; |
||||
} |
||||
|
||||
public function get_start_visible() |
||||
{ |
||||
return $this->start_visible; |
||||
} |
||||
|
||||
public function set_start_visible($value) |
||||
{ |
||||
$this->start_visible = $value; |
||||
} |
||||
|
||||
public function get_end_visible() |
||||
{ |
||||
return $this->end_visible; |
||||
} |
||||
|
||||
public function set_end_visible($value) |
||||
{ |
||||
$this->end_visible = $value; |
||||
} |
||||
|
||||
public function get_id_session() |
||||
{ |
||||
return $this->id_session; |
||||
} |
||||
|
||||
public function set_id_session($value) |
||||
{ |
||||
$this->id_session = $value; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,642 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file contains several classes related to portfolios management to avoid |
||||
* having too much files under the lib/. |
||||
* |
||||
* Once external libraries are moved to their own directory it would be worth |
||||
* moving them to their own files under a common portfolio directory. |
||||
*/ |
||||
|
||||
use Model\Document; |
||||
use Model\Course; |
||||
|
||||
/** |
||||
* A portfolio is used to present content to other people. In most cases it is |
||||
* an external application. |
||||
* |
||||
* From the application point of view it is an end point to which the user can send |
||||
* content. |
||||
* |
||||
* Available portfolios are configured in /main/inc/config/portfolio.conf.php |
||||
* |
||||
* The Portfolio class serves as an entry point to other portfolio components: |
||||
* |
||||
* - portfolio controller |
||||
* - portfolio share button |
||||
* - portfolio action |
||||
* |
||||
* Note: |
||||
* |
||||
* |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
class Portfolio extends Portfolio\Portfolio |
||||
{ |
||||
|
||||
/** |
||||
* Returns all portfolios available |
||||
* |
||||
* @return array |
||||
*/ |
||||
public static function all() |
||||
{ |
||||
$conf = Chamilo::path('/main/inc/conf/portfolio.conf.php'); |
||||
if (!is_readable($conf)) { |
||||
return array(); |
||||
} |
||||
include $conf; |
||||
return isset($portfolios) ? $portfolios : array(); |
||||
} |
||||
|
||||
/** |
||||
* Returns a portfolio from its name. |
||||
* |
||||
* @param string $name |
||||
* @return Portfolio\Portfolio |
||||
*/ |
||||
public static function get($name) |
||||
{ |
||||
$items = self::all(); |
||||
foreach ($items as $item) { |
||||
if ($item->get_name() == $name) { |
||||
return $item; |
||||
} |
||||
} |
||||
return Portfolio\Portfolio::none(); |
||||
} |
||||
|
||||
/** |
||||
* True if portfolios are enabled. False otherwise. |
||||
* |
||||
* @return boolean |
||||
*/ |
||||
public static function is_enabled() |
||||
{ |
||||
if (api_is_anonymous()) { |
||||
return false; |
||||
} |
||||
$user_id = api_get_user_id(); |
||||
if (empty($user_id)) { |
||||
return false; |
||||
} |
||||
$portfolios = self::all(); |
||||
if (count($portfolios) == 0) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* The controller for portfolio. |
||||
* |
||||
* @return \PortfolioController |
||||
*/ |
||||
public static function controller() |
||||
{ |
||||
return PortfolioController::instance(); |
||||
} |
||||
|
||||
/** |
||||
* Returns a share component/button. |
||||
* |
||||
* @param string $tool |
||||
* @param int $id |
||||
* @param array $attributes |
||||
* @return \PortfolioShare |
||||
*/ |
||||
public static function share($tool, $id, $attributes = array()) |
||||
{ |
||||
return PortfolioShare::factory($tool, $id, $attributes); |
||||
} |
||||
|
||||
/** |
||||
* Returns the list of actions. |
||||
* |
||||
* @return array |
||||
*/ |
||||
public static function actions() |
||||
{ |
||||
return PortfolioController::actions(); |
||||
} |
||||
|
||||
/** |
||||
* Returns a temporary url to download files and/or folders. |
||||
* |
||||
* @param string|array $ids |
||||
* @return string |
||||
*/ |
||||
public static function download_url($ids, $tool) |
||||
{ |
||||
$ids = is_array($ids) ? implode(',', $ids) : $ids; |
||||
|
||||
$params = Uri::course_params(); |
||||
$params['id'] = $ids; |
||||
$params[KeyAuth::PARAM_ACCESS_TOKEN] = KeyAuth::create_temp_token(); |
||||
$result = Uri::url("/main/$tool/file.php", $params, false); |
||||
return $result; |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* The portfolio controller. Responsible to dispatch/process portfolio actions. |
||||
* |
||||
* Usage: |
||||
* |
||||
* if(Porfolio::contoller()->accept()){ |
||||
* Portfolio::controller()->run(); |
||||
* } |
||||
* |
||||
* |
||||
*/ |
||||
class PortfolioController |
||||
{ |
||||
|
||||
const PARAM_ACTION = 'action'; |
||||
const PARAM_ID = 'id'; |
||||
const PARAM_TOOL = 'tool'; |
||||
const PARAM_PORTFOLIO = 'portfolio'; |
||||
const PARAM_CONTROLLER = 'controller'; |
||||
const PARAM_SECURITY_TOKEN = 'sec_token'; |
||||
const ACTION_SHARE = 'share'; |
||||
const NAME = 'portfolio'; |
||||
|
||||
/** |
||||
* |
||||
* @return \PortfolioController |
||||
*/ |
||||
static function instance() |
||||
{ |
||||
static $result = null; |
||||
if (empty($result)) { |
||||
$result = new self(); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
protected $message = ''; |
||||
|
||||
protected function __construct() |
||||
{ |
||||
|
||||
} |
||||
|
||||
public static function portfolios() |
||||
{ |
||||
return Portfolio::all(); |
||||
} |
||||
|
||||
/** |
||||
* List of actions for the SortableTable. |
||||
* |
||||
* @return array |
||||
*/ |
||||
public static function actions() |
||||
{ |
||||
static $result = null; |
||||
if (!is_null($result)) { |
||||
return $result; |
||||
} |
||||
|
||||
$items = self::portfolios(); |
||||
if (empty($items)) { |
||||
$result = array(); |
||||
return $result; |
||||
} |
||||
|
||||
$result = array(); |
||||
foreach ($items as $item) { |
||||
$action = PortfolioBulkAction::create($item); |
||||
$result[] = $action; |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
/** |
||||
* Returns true if the controller accept to process the current request. |
||||
* Returns false otherwise. |
||||
* |
||||
* @return boolean |
||||
*/ |
||||
function accept() |
||||
{ |
||||
if (!Portfolio::is_enabled()) { |
||||
return false; |
||||
} |
||||
$actions = self::actions(); |
||||
foreach ($actions as $action) { |
||||
if ($action->accept()) { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
if ($this->get_controller() != self::NAME) { |
||||
return false; |
||||
} |
||||
if (!Security::check_token('get')) { |
||||
return false; |
||||
} |
||||
$id = $this->get_id(); |
||||
if (empty($id)) { |
||||
return false; |
||||
} |
||||
|
||||
return $this->get_action() == self::ACTION_SHARE; |
||||
} |
||||
|
||||
/** |
||||
* Returns the value of the current controller request parameters. That is |
||||
* the name of the controller which shall handle the current request. |
||||
* |
||||
* @return string |
||||
*/ |
||||
function get_controller() |
||||
{ |
||||
return Request::get(self::PARAM_CONTROLLER); |
||||
} |
||||
|
||||
/** |
||||
* Returns the value of the action parameter. That is which action shall be |
||||
* performed. That is share to send an object to a portfolio. |
||||
* |
||||
* @return string |
||||
*/ |
||||
function get_action() |
||||
{ |
||||
$result = Request::get(self::PARAM_ACTION); |
||||
return ($result == self::ACTION_SHARE) ? self::ACTION_SHARE : ''; |
||||
} |
||||
|
||||
/** |
||||
* Returns the value of the id parameter: id of object to send. |
||||
* |
||||
* @return int |
||||
*/ |
||||
function get_id() |
||||
{ |
||||
return (int) Request::get(self::PARAM_ID); |
||||
} |
||||
|
||||
/** |
||||
* The course code (id) to which the object belongs. |
||||
* |
||||
* @return string |
||||
*/ |
||||
function course_code() |
||||
{ |
||||
return Chamilo::session()->course()->code(); |
||||
} |
||||
|
||||
/** |
||||
* The name of the porfolio where to send. |
||||
* |
||||
* @return type |
||||
*/ |
||||
function get_portfolio() |
||||
{ |
||||
return Request::get(self::PARAM_PORTFOLIO); |
||||
} |
||||
|
||||
/** |
||||
* Name of the tool: document, work, etc. Defaults to current_course_tool. |
||||
* |
||||
* @global string $current_course_tool |
||||
* @return string |
||||
*/ |
||||
function get_tool() |
||||
{ |
||||
global $current_course_tool; |
||||
return Request::get(self::PARAM_TOOL, $current_course_tool); |
||||
} |
||||
|
||||
/** |
||||
* Returns the end user message after running the controller.. |
||||
* @return string |
||||
*/ |
||||
function message() |
||||
{ |
||||
return $this->message; |
||||
} |
||||
|
||||
/** |
||||
* Execute the controller action as required. If a registered action accept |
||||
* the current request the controller calls it. |
||||
* |
||||
* If not action is accept the current request and current action is "share" |
||||
* the controller execute the "send to portfolio" action |
||||
* |
||||
* @return PortfolioController |
||||
*/ |
||||
function run() |
||||
{ |
||||
if (!$this->accept()) { |
||||
return $this; |
||||
} |
||||
|
||||
$actions = self::actions(); |
||||
foreach ($actions as $action) { |
||||
if ($action->accept()) { |
||||
return $action->run(); |
||||
} |
||||
} |
||||
|
||||
$action = $this->get_action(); |
||||
if ($action == self::ACTION_SHARE) { |
||||
|
||||
$user = new \Portfolio\User(); |
||||
$user->email = Chamilo::user()->email(); |
||||
|
||||
$tool = $this->get_tool(); |
||||
$id = $this->get_id(); |
||||
$url = Portfolio::download_url($id, $tool); |
||||
|
||||
$artefact = new Portfolio\Artefact($url); |
||||
|
||||
$name = $this->get_portfolio(); |
||||
$result = Portfolio::get($name)->send($user, $artefact); |
||||
if ($result) { |
||||
$this->message = Display::return_message(get_lang('SentSuccessful'), 'normal'); |
||||
} else { |
||||
$this->message = Display::return_message(get_lang('SentFailed'), 'error'); |
||||
} |
||||
return $this; |
||||
} else { |
||||
$this->message = ''; |
||||
} |
||||
return $this; |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* This component is used to display a "send to portfolio" button for a specific |
||||
* object. |
||||
* |
||||
* Note that the component implement the __toString() magic method and can be |
||||
* therefore used in situation where a string is expected: for ex echo $button. |
||||
* |
||||
* Usage |
||||
* |
||||
* $button = Portfolio::share(...); |
||||
* echo $button; |
||||
* |
||||
*/ |
||||
class PortfolioShare |
||||
{ |
||||
|
||||
/** |
||||
* Create a "send to portfolio" button |
||||
* |
||||
* @param string $tool The name of the tool: document, work. |
||||
* @param int $c_id The id of the course |
||||
* @param int $id The id of the object |
||||
* @param array $attributes Html attributes |
||||
* @return \PortfolioShare |
||||
*/ |
||||
static function factory($tool, $id, $attributes = array()) |
||||
{ |
||||
$result = new self($tool, $id, $attributes); |
||||
return $result; |
||||
} |
||||
|
||||
/** |
||||
* Returns the current secuirty token. Used to avoid see surfing attacks. |
||||
* |
||||
* @return type |
||||
*/ |
||||
static function security_token() |
||||
{ |
||||
static $result = null; |
||||
if (empty($result)) { |
||||
$result = Security::get_token(); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
protected $id = 0; |
||||
protected $attributes = array(); |
||||
protected $tool = ''; |
||||
|
||||
function __construct($tool, $id, $attributes = array()) |
||||
{ |
||||
$this->tool = $tool; |
||||
$this->id = (int) $id; |
||||
$this->attributes = $attributes; |
||||
} |
||||
|
||||
/** |
||||
* Object id to send |
||||
* @return int |
||||
*/ |
||||
function get_id() |
||||
{ |
||||
return $this->id; |
||||
} |
||||
|
||||
/** |
||||
* Object id to send |
||||
* @return int |
||||
*/ |
||||
function get_c_id() |
||||
{ |
||||
return $this->c_id; |
||||
} |
||||
|
||||
/** |
||||
* Html attributes. |
||||
* |
||||
* @return array |
||||
*/ |
||||
function get_attributes() |
||||
{ |
||||
return $this->attributes; |
||||
} |
||||
|
||||
/** |
||||
* Name of the tool. I.e. the type of the id parameter. Can be document, work. |
||||
* |
||||
* @return string |
||||
*/ |
||||
function get_tool() |
||||
{ |
||||
return $this->tool; |
||||
} |
||||
|
||||
/** |
||||
* Display the component. |
||||
* |
||||
* @return string |
||||
*/ |
||||
function display() |
||||
{ |
||||
if (!Portfolio::is_enabled()) { |
||||
return ''; |
||||
} |
||||
$id = $this->id; |
||||
$tool = $this->tool; |
||||
|
||||
$attributes = $this->attributes; |
||||
$attributes['z-index'] = 100000; |
||||
$s = ' '; |
||||
foreach ($attributes as $key => $value) { |
||||
$s .= $key . '="' . $value . '" '; |
||||
} |
||||
|
||||
$result = array(); |
||||
$result[] = '<span ' . $s . ' >'; |
||||
$result[] = '<span class="dropdown" >'; |
||||
$result[] = '<a href="#" data-toggle="dropdown" class="dropdown-toggle">'; |
||||
$result[] = Display::return_icon('document_send.png', get_lang('Send'), array(), ICON_SIZE_SMALL) . '<b class="caret"></b>'; |
||||
$result[] = '</a>'; |
||||
$result[] = '<ul class="dropdown-menu">'; |
||||
|
||||
$portfolios = Portfolio::all(); |
||||
foreach ($portfolios as $portfolio) { |
||||
$parameters = Uri::course_params(); |
||||
$parameters[PortfolioController::PARAM_ACTION] = PortfolioController::ACTION_SHARE; |
||||
$parameters[PortfolioController::PARAM_CONTROLLER] = PortfolioController::NAME; |
||||
$parameters[PortfolioController::PARAM_PORTFOLIO] = $portfolio->get_name(); |
||||
$parameters[PortfolioController::PARAM_SECURITY_TOKEN] = self::security_token(); |
||||
$parameters[PortfolioController::PARAM_TOOL] = $this->get_tool(); |
||||
$parameters[PortfolioController::PARAM_ID] = $id; |
||||
$parameters[PortfolioController::PARAM_TOOL] = $tool; |
||||
$url = Chamilo::url('/main/portfolio/share.php', $parameters); |
||||
$result[] = '<li>'; |
||||
$result[] = '<a href="' . $url . '">' . $portfolio->get_title() . '</a>'; |
||||
$result[] = '</li>'; |
||||
} |
||||
$result[] = '</ul>'; |
||||
$result[] = '</span>'; |
||||
$result[] = '</span>'; |
||||
return implode("\n", $result); |
||||
} |
||||
|
||||
function __toString() |
||||
{ |
||||
return $this->display(); |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* A "send to this portfolio" action. Actions are used by the SortableTable to |
||||
* perform actions on a set of objects. An action is composed of |
||||
* |
||||
* - a name |
||||
* - a title (displayed to the user) |
||||
* - code to execute |
||||
* |
||||
* Usage: |
||||
* |
||||
* $form_actions = array(); |
||||
* $form_action['...'] = get_lang('...'); |
||||
* $portfolio_actions = Portfolio::actions(); |
||||
* foreach($portfolio_actions as $action){ |
||||
* $form_action[$action->get_name()] = $action->get_title(); |
||||
* } |
||||
* $table->set_form_actions($form_action, 'path'); |
||||
* |
||||
* @see SortableTable |
||||
*/ |
||||
class PortfolioBulkAction |
||||
{ |
||||
|
||||
/** |
||||
* |
||||
* @param \Portfolio\Portfolio $portfolio |
||||
* @return PortfolioBulkAction |
||||
*/ |
||||
public static function create($portfolio) |
||||
{ |
||||
return new self($portfolio); |
||||
} |
||||
|
||||
protected $name = ''; |
||||
protected $title = ''; |
||||
protected $portfolio = null; |
||||
|
||||
/** |
||||
* |
||||
* @param \Portfolio\Portfolio $portfolio |
||||
*/ |
||||
public function __construct($portfolio) |
||||
{ |
||||
$this->name = md5(__CLASS__) . '_' . $portfolio->get_name(); |
||||
$this->title = $portfolio->get_title() ? $portfolio->get_title() : get_lang('SendTo') . ' ' . $portfolio->get_name(); |
||||
$this->portfolio = $portfolio; |
||||
} |
||||
|
||||
public function get_name() |
||||
{ |
||||
return $this->name; |
||||
} |
||||
|
||||
public function get_title() |
||||
{ |
||||
return $this->title; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @return \Portfolio\Portfolio |
||||
*/ |
||||
public function get_portfolio() |
||||
{ |
||||
return $this->portfolio; |
||||
} |
||||
|
||||
public function accept() |
||||
{ |
||||
$name = $this->get_name(); |
||||
$action = Request::get(PortfolioController::PARAM_ACTION); |
||||
if ($name != $action) { |
||||
return false; |
||||
} |
||||
$pathes = Request::get('path'); |
||||
if (empty($pathes)) { |
||||
return false; |
||||
} |
||||
|
||||
$course = Course::current(); |
||||
if (empty($course)) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
public function run() |
||||
{ |
||||
if (!$this->accept()) { |
||||
return false; |
||||
} |
||||
|
||||
$course = Course::current(); |
||||
|
||||
$pathes = Request::get('path'); |
||||
$pathes = is_array($pathes) ? $pathes : array($pathes); |
||||
|
||||
$ids = array(); |
||||
foreach ($pathes as $path) { |
||||
$doc = Document::get_by_path($course, $path); |
||||
if ($doc) { |
||||
$ids[] = $doc->get_id(); |
||||
} |
||||
} |
||||
if (empty($ids)) { |
||||
return false; |
||||
} |
||||
|
||||
$user = new \Portfolio\User(); |
||||
$user->email = Chamilo::user()->email(); |
||||
|
||||
$artefact = new Portfolio\Artefact(); |
||||
$artefact->url = Portfolio::download_url($ids); |
||||
|
||||
$portfolio = $this->get_portfolio(); |
||||
$result = $portfolio->send($user, $artefact); |
||||
return $result; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,23 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* To change this template, choose Tools | Templates |
||||
* and open the template in the editor. |
||||
*/ |
||||
|
||||
/** |
||||
* Description of response |
||||
* |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
class Response |
||||
{ |
||||
|
||||
public static function not_found() |
||||
{ |
||||
Header::response_code(404); |
||||
exit; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,439 @@ |
||||
<?php |
||||
|
||||
namespace Model; |
||||
|
||||
use Database; |
||||
use ResultSet; |
||||
|
||||
/** |
||||
* Represent a database "student_publication" object. |
||||
* |
||||
* Note: |
||||
* |
||||
* Each database column is mapped to a property. |
||||
* |
||||
* The item_property table is available through its own property but is loaded |
||||
* alongside document data. |
||||
* |
||||
* Some db query functions exists in this class and would need to be adapted |
||||
* to Symphony once it is moved to production. Yet the object structure should |
||||
* stay. |
||||
* |
||||
* @see \Model\ItemProperty |
||||
* @see table c_student_publication |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
class StudentPublication |
||||
{ |
||||
|
||||
public static function void() |
||||
{ |
||||
static $result = null; |
||||
if($result) |
||||
{ |
||||
return $result; |
||||
} |
||||
|
||||
$result = new self(); |
||||
return $result; |
||||
} |
||||
|
||||
|
||||
|
||||
/** |
||||
* |
||||
* @param string $where |
||||
* @return \ResultSet |
||||
*/ |
||||
public static function query($where) |
||||
{ |
||||
$table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY); |
||||
$table = Database::get_course_table(TABLE_STUDENT_PUBLICATION); |
||||
$tool = 'work'; |
||||
|
||||
$sql = "SELECT pub.*, |
||||
prop.id AS property_id, |
||||
prop.tool, |
||||
prop.insert_user_id, |
||||
prop.insert_date, |
||||
prop.lastedit_date, |
||||
prop.ref, |
||||
prop.lastedit_type, |
||||
prop.lastedit_user_id, |
||||
prop.to_group_id, |
||||
prop.to_user_id, |
||||
prop.visibility, |
||||
prop.start_visible, |
||||
prop.end_visible, |
||||
prop.id_session |
||||
FROM |
||||
$table AS pub, |
||||
$table_item_property AS prop |
||||
WHERE |
||||
(pub.id = prop.ref AND |
||||
pub.c_id = prop.c_id AND |
||||
prop.tool = '$tool')"; |
||||
|
||||
$sql .= $where ? "AND ($where)" : ''; |
||||
$result = new ResultSet($sql); |
||||
return $result->return_type(__CLASS__); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param int|Course $c_id |
||||
* @param int $id |
||||
* @return \Model\StudentPublication |
||||
*/ |
||||
public static function get_by_id($c_id, $id) |
||||
{ |
||||
$c_id = is_object($c_id) ? $c_id->get_id() : (int) $c_id; |
||||
return self::query("pub.c_id = $c_id AND pub.id = $id")->first(); |
||||
} |
||||
|
||||
protected $c_id = 0; |
||||
protected $id = 0; |
||||
protected $url = ''; |
||||
protected $title = ''; |
||||
protected $description = ''; |
||||
protected $author = ''; |
||||
protected $active = null; |
||||
protected $accepted = false; |
||||
protected $post_group_id = 0; |
||||
protected $sent_date = 0; |
||||
protected $filetype = ''; |
||||
protected $has_properties = 0; |
||||
protected $view_properties = null; |
||||
protected $qualification = 0; |
||||
protected $date_of_qualification = 0; |
||||
protected $parent_id = 0; |
||||
protected $qualificator_id = 0; |
||||
protected $weight = 0; |
||||
protected $session_id = 0; |
||||
protected $user_id = null; |
||||
protected $allow_text_assignment = 0; |
||||
protected $contains_file = 0; |
||||
protected $course = null; |
||||
protected $item_property = null; |
||||
|
||||
public function __construct($data) |
||||
{ |
||||
$data = (object) $data; |
||||
$this->c_id = (int) $data->c_id; |
||||
$this->id = (int) $data->id; |
||||
$this->url = $data->url; |
||||
$this->title = $data->title; |
||||
$this->description = $data->description; |
||||
$this->author = $data->author; |
||||
$this->active = $data->active; |
||||
$this->accepted = $data->accepted; |
||||
$this->post_group_id = $data->post_group_id; |
||||
$this->sent_date = $data->sent_date; |
||||
$this->filetype = $data->filetype; |
||||
$this->has_properties = $data->has_properties; |
||||
$this->view_properties = $data->view_properties; |
||||
$this->qualification = $data->qualification; |
||||
$this->date_of_qualification = $data->date_of_qualification; |
||||
$this->parent_id = $data->parent_id; |
||||
$this->qualificator_id = $data->qualificator_id; |
||||
$this->weight = $data->weight; |
||||
$this->session_id = $data->session_id; |
||||
$this->user_id = $data->user_id; |
||||
$this->allow_text_assignment = $data->allow_text_assignment; |
||||
$this->contains_file = $data->contains_file; |
||||
$this->course = $data->course; |
||||
$this->item_property = $data->item_property; |
||||
|
||||
$this->course = null; |
||||
|
||||
if (isset($data->property_id)) { |
||||
$property = (array) $data; |
||||
$property = (object) $property; |
||||
$property->id = $property->property_id; |
||||
$this->item_property = ItemProperty::create($property); |
||||
} else { |
||||
$this->item_property = null; |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
public function get_c_id() |
||||
{ |
||||
return $this->c_id; |
||||
} |
||||
|
||||
public function set_c_id($value) |
||||
{ |
||||
$this->c_id = $value; |
||||
} |
||||
|
||||
public function get_id() |
||||
{ |
||||
return $this->id; |
||||
} |
||||
|
||||
public function set_id($value) |
||||
{ |
||||
$this->id = $value; |
||||
} |
||||
|
||||
public function get_url() |
||||
{ |
||||
return $this->url; |
||||
} |
||||
|
||||
public function set_url($value) |
||||
{ |
||||
$this->url = $value; |
||||
} |
||||
|
||||
public function get_title() |
||||
{ |
||||
return $this->title; |
||||
} |
||||
|
||||
public function set_title($value) |
||||
{ |
||||
$this->title = $value; |
||||
} |
||||
|
||||
public function get_description() |
||||
{ |
||||
return $this->description; |
||||
} |
||||
|
||||
public function set_description($value) |
||||
{ |
||||
$this->description = $value; |
||||
} |
||||
|
||||
public function get_author() |
||||
{ |
||||
return $this->author; |
||||
} |
||||
|
||||
public function set_author($value) |
||||
{ |
||||
$this->author = $value; |
||||
} |
||||
|
||||
public function get_active() |
||||
{ |
||||
return $this->active; |
||||
} |
||||
|
||||
public function set_active($value) |
||||
{ |
||||
$this->active = $value; |
||||
} |
||||
|
||||
public function get_accepted() |
||||
{ |
||||
return $this->accepted; |
||||
} |
||||
|
||||
public function set_accepted($value) |
||||
{ |
||||
$this->accepted = $value; |
||||
} |
||||
|
||||
public function get_post_group_id() |
||||
{ |
||||
return $this->post_group_id; |
||||
} |
||||
|
||||
public function set_post_group_id($value) |
||||
{ |
||||
$this->post_group_id = $value; |
||||
} |
||||
|
||||
public function get_sent_date() |
||||
{ |
||||
return $this->sent_date; |
||||
} |
||||
|
||||
public function set_sent_date($value) |
||||
{ |
||||
$this->sent_date = $value; |
||||
} |
||||
|
||||
public function get_filetype() |
||||
{ |
||||
return $this->filetype; |
||||
} |
||||
|
||||
public function set_filetype($value) |
||||
{ |
||||
$this->filetype = $value; |
||||
} |
||||
|
||||
public function get_has_properties() |
||||
{ |
||||
return $this->has_properties; |
||||
} |
||||
|
||||
public function set_has_properties($value) |
||||
{ |
||||
$this->has_properties = $value; |
||||
} |
||||
|
||||
public function get_view_properties() |
||||
{ |
||||
return $this->view_properties; |
||||
} |
||||
|
||||
public function set_view_properties($value) |
||||
{ |
||||
$this->view_properties = $value; |
||||
} |
||||
|
||||
public function get_qualification() |
||||
{ |
||||
return $this->qualification; |
||||
} |
||||
|
||||
public function set_qualification($value) |
||||
{ |
||||
$this->qualification = $value; |
||||
} |
||||
|
||||
public function get_date_of_qualification() |
||||
{ |
||||
return $this->date_of_qualification; |
||||
} |
||||
|
||||
public function set_date_of_qualification($value) |
||||
{ |
||||
$this->date_of_qualification = $value; |
||||
} |
||||
|
||||
public function get_parent_id() |
||||
{ |
||||
return $this->parent_id; |
||||
} |
||||
|
||||
public function set_parent_id($value) |
||||
{ |
||||
$this->parent_id = $value; |
||||
} |
||||
|
||||
public function get_qualificator_id() |
||||
{ |
||||
return $this->qualificator_id; |
||||
} |
||||
|
||||
public function set_qualificator_id($value) |
||||
{ |
||||
$this->qualificator_id = $value; |
||||
} |
||||
|
||||
public function get_weight() |
||||
{ |
||||
return $this->weight; |
||||
} |
||||
|
||||
public function set_weight($value) |
||||
{ |
||||
$this->weight = $value; |
||||
} |
||||
|
||||
public function get_session_id() |
||||
{ |
||||
return $this->session_id; |
||||
} |
||||
|
||||
public function set_session_id($value) |
||||
{ |
||||
$this->session_id = $value; |
||||
} |
||||
|
||||
public function get_user_id() |
||||
{ |
||||
return $this->user_id; |
||||
} |
||||
|
||||
public function set_user_id($value) |
||||
{ |
||||
$this->user_id = $value; |
||||
} |
||||
|
||||
public function get_allow_text_assignment() |
||||
{ |
||||
return $this->allow_text_assignment; |
||||
} |
||||
|
||||
public function set_allow_text_assignment($value) |
||||
{ |
||||
$this->allow_text_assignment = $value; |
||||
} |
||||
|
||||
public function get_contains_file() |
||||
{ |
||||
return $this->contains_file; |
||||
} |
||||
|
||||
public function set_contains_file($value) |
||||
{ |
||||
$this->contains_file = $value; |
||||
} |
||||
|
||||
public function is_folder() |
||||
{ |
||||
return $this->filetype == 'folder'; |
||||
} |
||||
|
||||
public function is_file() |
||||
{ |
||||
return $this->filetype == 'file'; |
||||
} |
||||
|
||||
public function is_visible() |
||||
{ |
||||
$this->get_item_property()->get_visibility() == 1; |
||||
} |
||||
|
||||
public function is_accessible($user = null) |
||||
{ |
||||
$user_id = $user ? $user : api_get_user_id(); |
||||
$result = $this->is_visible() || $this->get_user_id() == $user_id || api_is_allowed_to_edit(); |
||||
return $result; |
||||
} |
||||
|
||||
public function get_absolute_path() |
||||
{ |
||||
return api_get_path(SYS_COURSE_PATH) . api_get_course_path() . '/' . $this->get_url(); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @return \Model\ItemProperty |
||||
*/ |
||||
public function get_item_property() |
||||
{ |
||||
if ($this->item_property && $this->item_property->get_c_id() == $this->c_id && $this->item_property->get_ref() == $this->id) { |
||||
return $this->item_property; |
||||
} |
||||
|
||||
$this->item_property = ItemProperty::get_by_ref($this->id, TOOL_DOCUMENT); |
||||
return $this->item_property; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param bool $all |
||||
* @return ResultSet|array |
||||
*/ |
||||
public function get_children() |
||||
{ |
||||
if (!$this->is_folder()) { |
||||
return array(); |
||||
} |
||||
$id = $this->id; |
||||
$c_id = $this->c_id; |
||||
$where = "pub.c_id = $c_id AND pub.parent_id = $id"; |
||||
return self::query($where); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,145 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* Temporary file/folder. The file/folder is automatically deleted at |
||||
* the end of the script/during garbage collection. |
||||
* |
||||
* The object implements __toString so it can be used as string variable. |
||||
* |
||||
* Usage |
||||
* |
||||
* $path = Temp::file(); |
||||
* file_puts_content($path, $content); |
||||
* |
||||
* or |
||||
* |
||||
* $path = Temp::dir(); |
||||
* ... |
||||
* |
||||
* @copyright (c) 2012 University of Geneva |
||||
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html |
||||
* @author Laurent Opprecht <laurent@opprecht.info> |
||||
*/ |
||||
class Temp |
||||
{ |
||||
|
||||
/** |
||||
* Recursively delete files and/or folders. |
||||
* |
||||
* @param string $path |
||||
* @return boolean |
||||
*/ |
||||
public static function delete($path) |
||||
{ |
||||
if (!file_exists($path)) { |
||||
return false; |
||||
} |
||||
|
||||
if (is_file($path)) { |
||||
unlink($path); |
||||
return true; |
||||
} |
||||
$files = scandir($path); |
||||
$files = array_diff($files, array('.', '..')); |
||||
foreach ($files as $file) { |
||||
self::delete($file); |
||||
} |
||||
rmdir($path); |
||||
} |
||||
|
||||
private static $temp_root = ''; |
||||
|
||||
/** |
||||
* Set the temp root directory. Temporary files are by default created in this directory. |
||||
* Defaults to sys_get_temp_dir(). |
||||
* |
||||
* @param string $value |
||||
*/ |
||||
public static function set_temp_root($value) |
||||
{ |
||||
self::$temp_root = $value; |
||||
} |
||||
|
||||
public static function get_temp_root() |
||||
{ |
||||
if (empty(self::$temp_root)) { |
||||
self::$temp_root = sys_get_temp_dir(); |
||||
} |
||||
|
||||
return self::$temp_root; |
||||
} |
||||
|
||||
/** |
||||
* Returns a path to a non-existing temporary file located under temp_dir. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public static function get_temporary_name() |
||||
{ |
||||
$result = self::get_temp_root() . '/' . md5(uniqid('tmp', true)); |
||||
while (file_exists($result)) { |
||||
$result = self::get_temp_root() . '/' . md5(uniqid('tmp', true)); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param string $path |
||||
* @return Temp |
||||
*/ |
||||
public static function file($path = '') |
||||
{ |
||||
$path = $path ? $path : self::get_temporary_name(); |
||||
return new self($path); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param string $path |
||||
* @return Temp |
||||
*/ |
||||
public static function dir($path = '') |
||||
{ |
||||
$path = $path ? $path : self::get_temporary_name(); |
||||
if (!file_exists($path)) { |
||||
mkdir($path, 0777, $true); |
||||
} |
||||
return new self($path); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param string $path |
||||
* @return Temp |
||||
*/ |
||||
public static function create($path = '') |
||||
{ |
||||
$path = $path ? $path : self::get_temporary_name(); |
||||
return new self($path); |
||||
} |
||||
|
||||
protected $path = ''; |
||||
|
||||
function __construct($path = '') |
||||
{ |
||||
$this->path = $path; |
||||
} |
||||
|
||||
function get_path() |
||||
{ |
||||
return $this->path; |
||||
} |
||||
|
||||
function __toString() |
||||
{ |
||||
return $this->path; |
||||
} |
||||
|
||||
function __destruct() |
||||
{ |
||||
$path = $this->path; |
||||
self::delete($path); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,131 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* |
||||
* @copyright (c) 2012 University of Geneva |
||||
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html |
||||
* @author Laurent Opprecht <laurent@opprecht.info> |
||||
*/ |
||||
class Curl |
||||
{ |
||||
|
||||
protected static $default_options = array(); |
||||
|
||||
static function get_default_options($options = array()) |
||||
{ |
||||
if (empty(self::$default_options)) { |
||||
self::$default_options[CURLOPT_HEADER] = false; |
||||
self::$default_options[CURLOPT_RETURNTRANSFER] = true; |
||||
self::$default_options[CURLOPT_SSL_VERIFYPEER] = false; |
||||
} |
||||
|
||||
$result = self::$default_options; |
||||
foreach ($options as $key => $value) { |
||||
$result[$key] = $value; |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
static function set_default_option($key, $value) |
||||
{ |
||||
$options = $this->get_options(array($key => $value)); |
||||
self::$default_options = $options; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param string $url |
||||
* @param array $options |
||||
* @return Curl |
||||
*/ |
||||
static function get($url, $options = array()) |
||||
{ |
||||
$options[CURLOPT_HTTPGET] = true; |
||||
$result = new self($url, $options); |
||||
return $result; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param string $url |
||||
* @param array $fields |
||||
* @param array $options |
||||
* @return Curl |
||||
*/ |
||||
static function post($url, $fields, $options = array()) |
||||
{ |
||||
$options[CURLOPT_POST] = true; |
||||
$options[CURLOPT_POSTFIELDS] = $fields; |
||||
$result = new self($url, $options); |
||||
return $result; |
||||
} |
||||
|
||||
protected $url = ''; |
||||
protected $options = array(); |
||||
protected $content = ''; |
||||
protected $info = array(); |
||||
protected $error = ''; |
||||
protected $error_no = 0; |
||||
|
||||
function __construct($url, $options = array()) |
||||
{ |
||||
$this->url = $url; |
||||
$this->options = self::get_default_options($options); |
||||
} |
||||
|
||||
function url() |
||||
{ |
||||
return $this->url; |
||||
} |
||||
|
||||
function options() |
||||
{ |
||||
return $this->options; |
||||
} |
||||
|
||||
function execute() |
||||
{ |
||||
$ch = curl_init(); |
||||
|
||||
$options = $this->options; |
||||
$options[CURLOPT_URL] = $this->url; |
||||
curl_setopt_array($ch, $options); |
||||
|
||||
$this->content = curl_exec($ch); |
||||
$this->error = curl_error($ch); |
||||
$this->info = curl_getinfo($ch); |
||||
$this->error_no = curl_errno($ch); |
||||
|
||||
curl_close($ch); |
||||
|
||||
return $this->content; |
||||
} |
||||
|
||||
function content() |
||||
{ |
||||
return $this->content; |
||||
} |
||||
|
||||
/** |
||||
* @return array|string |
||||
*/ |
||||
function info($key = false) |
||||
{ |
||||
if ($key) { |
||||
return isset($this->info[$key]) ? $this->info[$key] : false; |
||||
} else { |
||||
return $this->info; |
||||
} |
||||
} |
||||
|
||||
function error() |
||||
{ |
||||
return $this->error; |
||||
} |
||||
|
||||
function error_no() |
||||
{ |
||||
return $this->error_no; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,72 @@ |
||||
<?php |
||||
|
||||
namespace net; |
||||
|
||||
use Curl; |
||||
|
||||
/** |
||||
* Description of channel |
||||
* |
||||
* @copyright (c) 2012 University of Geneva |
||||
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html |
||||
* @author Laurent Opprecht <laurent@opprecht.info> |
||||
*/ |
||||
class HttpChannel |
||||
{ |
||||
|
||||
/** |
||||
* |
||||
* @param string $url |
||||
* @param type $modules |
||||
* @return HttpChannel |
||||
*/ |
||||
static function create($url, $modules = array()) |
||||
{ |
||||
return new self($url, $modules); |
||||
} |
||||
|
||||
protected $base_url = ''; |
||||
protected $modules = array(); |
||||
|
||||
public function __construct($base_url = '', $modules = array()) |
||||
{ |
||||
$this->base_url = $base_url; |
||||
$this->modules = $modules; |
||||
} |
||||
|
||||
function modules() |
||||
{ |
||||
return $this->modules; |
||||
} |
||||
|
||||
function get($url, $parameters) |
||||
{ |
||||
$options = $this->get_options(); |
||||
$url = $this->base_url . $url; |
||||
return Curl::get($url, $options)->execute(); |
||||
} |
||||
|
||||
function post($url, $fields) |
||||
{ |
||||
$options = $this->get_options(); |
||||
$url = $this->base_url . $url; |
||||
return Curl::post($url, $fields, $options)->execute(); |
||||
} |
||||
|
||||
protected function get_options() |
||||
{ |
||||
$result = array(); |
||||
$modules = $this->modules(); |
||||
foreach ($modules as $module) { |
||||
if (is_array($module)) { |
||||
$options = $module; |
||||
} else { |
||||
|
||||
$options = $module->get_options(); |
||||
} |
||||
$result = array_merge($result, $options); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,149 @@ |
||||
<?php |
||||
|
||||
namespace Portfolio; |
||||
|
||||
/** |
||||
* An artefact is any object the user can display in its portfolio. |
||||
* |
||||
* The artefact point either to a local file or to a url from which the object's content |
||||
* can be fetched. |
||||
* |
||||
* Usage |
||||
* |
||||
* $artefact = new artefact(); |
||||
* $artefact->set_path('...'); |
||||
* |
||||
* or |
||||
* |
||||
* |
||||
* $artefact = new artefact(); |
||||
* $artefact->set_url('...'); |
||||
* |
||||
* @copyright (c) 2012 University of Geneva |
||||
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html |
||||
* @author Laurent Opprecht <laurent@opprecht.info> |
||||
*/ |
||||
class Artefact |
||||
{ |
||||
|
||||
protected $id = ''; |
||||
protected $mime_type = ''; |
||||
protected $name = ''; |
||||
protected $description = ''; |
||||
protected $path = ''; |
||||
protected $url = ''; |
||||
protected $creation_date = ''; |
||||
protected $modification_date = ''; |
||||
protected $metadata = null; |
||||
|
||||
/** |
||||
* |
||||
* @param string $file Either url or file path |
||||
*/ |
||||
public function __construct($file = '') |
||||
{ |
||||
if ($file) { |
||||
if (strpos($file, 'http') !== false) { |
||||
$this->url = $file; |
||||
} else { |
||||
$this->path = $file; |
||||
} |
||||
} |
||||
$this->id = uniqid('', true); |
||||
$this->mime_type = ''; |
||||
$time = time(); |
||||
$this->creation_date = $time; |
||||
$this->modification_date = $time; |
||||
} |
||||
|
||||
public function get_id() |
||||
{ |
||||
return $this->id; |
||||
} |
||||
|
||||
public function set_id($value) |
||||
{ |
||||
$this->id = $value; |
||||
} |
||||
|
||||
public function get_name() |
||||
{ |
||||
return $this->name; |
||||
} |
||||
|
||||
public function set_name($value) |
||||
{ |
||||
$this->name = $value; |
||||
} |
||||
|
||||
public function get_mime_type() |
||||
{ |
||||
return $this->mime_type; |
||||
} |
||||
|
||||
public function set_mime_type($value) |
||||
{ |
||||
$this->mime_type = $value; |
||||
} |
||||
|
||||
public function get_description() |
||||
{ |
||||
return $this->description; |
||||
} |
||||
|
||||
public function set_description($value) |
||||
{ |
||||
$this->description = $value; |
||||
} |
||||
|
||||
public function get_path() |
||||
{ |
||||
return $this->path; |
||||
} |
||||
|
||||
public function set_path($value) |
||||
{ |
||||
$this->path = $value; |
||||
} |
||||
|
||||
public function get_url() |
||||
{ |
||||
return $this->url; |
||||
} |
||||
|
||||
public function set_url($value) |
||||
{ |
||||
$this->url = $value; |
||||
} |
||||
|
||||
public function get_creation_date() |
||||
{ |
||||
return $this->creation_date; |
||||
} |
||||
|
||||
public function set_creation_date($value) |
||||
{ |
||||
$this->creation_date = $value; |
||||
} |
||||
|
||||
public function get_modification_date() |
||||
{ |
||||
return $this->modification_date; |
||||
} |
||||
|
||||
public function set_modification_date($value) |
||||
{ |
||||
$this->modification_date = $value; |
||||
} |
||||
|
||||
public function get_metadata() |
||||
{ |
||||
return $this->metadata; |
||||
} |
||||
|
||||
public function set_metadata($value) |
||||
{ |
||||
$this->metadata = $value; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,35 @@ |
||||
<?php |
||||
|
||||
namespace Portfolio; |
||||
|
||||
use Header; |
||||
|
||||
/** |
||||
* Download file to your desktop |
||||
* |
||||
* @copyright (c) 2012 University of Geneva |
||||
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html |
||||
* @author Laurent Opprecht <laurent@opprecht.info> |
||||
*/ |
||||
class Download extends Portfolio |
||||
{ |
||||
|
||||
function __construct() |
||||
{ |
||||
parent::__construct('download', null); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param User $user |
||||
* @param Artefact $artefact |
||||
* @return bool |
||||
*/ |
||||
function send($user, $artefact) |
||||
{ |
||||
if ($artefact->get_url()) { |
||||
Header::location($artefact->get_url()); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,52 @@ |
||||
<?php |
||||
|
||||
namespace Portfolio; |
||||
|
||||
use Header; |
||||
|
||||
/** |
||||
* Interface with a Mahara portfolio. |
||||
* |
||||
* This class requires that the connect mahara plugin is installed and enabled. |
||||
* |
||||
* @see https://mahara.org/ |
||||
* @copyright (c) 2012 University of Geneva |
||||
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html |
||||
* @author Laurent Opprecht <laurent@opprecht.info> |
||||
*/ |
||||
class Mahara extends Portfolio |
||||
{ |
||||
|
||||
protected $url = ''; |
||||
|
||||
/** |
||||
* |
||||
* @param string $url The root url |
||||
*/ |
||||
function __construct($url) |
||||
{ |
||||
parent::__construct('Mahara', null); |
||||
$this->url = $url; |
||||
} |
||||
|
||||
function get_url() |
||||
{ |
||||
return $this->url; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param User $user |
||||
* @param Artefact $artefact |
||||
* @return bool |
||||
*/ |
||||
function send($user, $artefact) |
||||
{ |
||||
$root = $this->get_url(); |
||||
rtrim($root, '/'); |
||||
$url = $artefact->get_url(); |
||||
$url = $root . '/artefact/connect/upload.php?url=' . urlencode($url) . '&extract=true'; |
||||
Header::location($url); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,106 @@ |
||||
<?php |
||||
|
||||
namespace Portfolio; |
||||
|
||||
/** |
||||
* Portfolio are used to display and share content. The porfolio class represents |
||||
* one (external) portfolio application and allows to share content with an it. |
||||
* |
||||
* @copyright (c) 2012 University of Geneva |
||||
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html |
||||
* @author Laurent Opprecht <laurent@opprecht.info> |
||||
*/ |
||||
class Portfolio |
||||
{ |
||||
|
||||
public static function none() |
||||
{ |
||||
static $result = null; |
||||
if (empty($result)) { |
||||
$result = new self('empty', null); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
public static function all() |
||||
{ |
||||
|
||||
} |
||||
|
||||
protected $name; |
||||
protected $title = ''; |
||||
protected $description = ''; |
||||
protected $channel; |
||||
|
||||
function __construct($name, $channel = null) |
||||
{ |
||||
$this->name = $name; |
||||
$this->title = $name; |
||||
$this->channel = $channel; |
||||
} |
||||
|
||||
/** |
||||
* The name of the portfolio - i.e. the unique id. |
||||
* @return type |
||||
*/ |
||||
function get_name() |
||||
{ |
||||
return $this->name; |
||||
} |
||||
|
||||
/** |
||||
* Title for the end user. |
||||
* |
||||
* @return type |
||||
*/ |
||||
function get_title() |
||||
{ |
||||
return $this->title; |
||||
} |
||||
|
||||
function set_title($value) |
||||
{ |
||||
$this->title = $value; |
||||
} |
||||
|
||||
/** |
||||
* Description for the end user. |
||||
* |
||||
* @return type |
||||
*/ |
||||
function get_description() |
||||
{ |
||||
return $this->description; |
||||
} |
||||
|
||||
function set_description($value) |
||||
{ |
||||
$this->description = $value; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @return HttpChannel |
||||
*/ |
||||
function channel() |
||||
{ |
||||
return $this->channel; |
||||
} |
||||
|
||||
function __toString() |
||||
{ |
||||
return $this->name; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param User $user |
||||
* @param Artefact $artefact |
||||
* @return bool |
||||
*/ |
||||
function send($user, $artefact) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,19 @@ |
||||
<?php |
||||
|
||||
namespace Portfolio; |
||||
|
||||
/** |
||||
* A portfolio user is used to share identity between two applications. |
||||
* Not used at this point. |
||||
* |
||||
* @copyright (c) 2012 University of Geneva |
||||
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html |
||||
* @author Laurent Opprecht <laurent@opprecht.info> |
||||
*/ |
||||
class User |
||||
{ |
||||
public $id; |
||||
public $email; |
||||
public $token; |
||||
|
||||
} |
@ -0,0 +1,81 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* Header utility functions. |
||||
* |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
class Header |
||||
{ |
||||
|
||||
public static function response_code($response_code) |
||||
{ |
||||
if (function_exists('http_response_code')) { |
||||
http_response_code($response_code); |
||||
return; |
||||
} |
||||
|
||||
switch ($response_code) { |
||||
case 400: |
||||
header("HTTP/1.0 $response_code Bad Request"); |
||||
case 401: |
||||
header("HTTP/1.0 $response_code Unauthorized"); |
||||
case 402: |
||||
header("HTTP/1.0 $response_code Payment Required"); |
||||
case 403: |
||||
header("HTTP/1.0 $response_code Forbidden"); |
||||
case 404: |
||||
header("HTTP/1.0 $response_code Not Found"); |
||||
default: |
||||
header("HTTP/1.0 $response_code"); |
||||
} |
||||
} |
||||
|
||||
public static function content_type($mime_type, $charset = '') |
||||
{ |
||||
if (empty($mime_type)) { |
||||
return; |
||||
} |
||||
$type = $charset ? "$mime_type;charset=$charset" : $mime_type; |
||||
header('Content-type: ' . $type); |
||||
} |
||||
|
||||
public static function content_type_xml() |
||||
{ |
||||
header('Content-type: text/xml'); |
||||
} |
||||
|
||||
public static function content_type_javascript() |
||||
{ |
||||
header('Content-type: application/javascript'); |
||||
} |
||||
|
||||
/** |
||||
* Redirect the navigator to the specified url. |
||||
* |
||||
* @param string $url |
||||
*/ |
||||
public static function location($url) |
||||
{ |
||||
header("Location: $url"); |
||||
exit; |
||||
} |
||||
|
||||
public static function expires($timestamp) |
||||
{ |
||||
$value = gmdate('D, d M Y H:i:s \G\M\T', $timestamp); |
||||
header('Expires: ' . $value); |
||||
} |
||||
|
||||
public static function cache_control($value) |
||||
{ |
||||
header('Cache-Control: ' . $value); |
||||
} |
||||
|
||||
public static function pragma($value) |
||||
{ |
||||
header('Pragma: ' . $value); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,103 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* Manage user api keys |
||||
* |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
class UserApiKeyManager |
||||
{ |
||||
|
||||
/** |
||||
* The name of the default service. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public static function default_service() |
||||
{ |
||||
return 'chamilo'; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public static function end_of_time() |
||||
{ |
||||
$time = 2147483647; //mysql int max value |
||||
} |
||||
|
||||
public static function get_by_id($id) |
||||
{ |
||||
$table = Database::get_main_table(TABLE_MAIN_USER_API_KEY); |
||||
$sql = "SELECT * FROM $table WHERE id=$id"; |
||||
$res = Database::query($sql); |
||||
if (Database::num_rows($res) < 1) { |
||||
return false; |
||||
} |
||||
$result = Database::fetch_array($res, 'ASSOC'); |
||||
return $result; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param int $duration in seconds |
||||
* @param int $user_id |
||||
* @param string $api_service |
||||
* @param string $api_end_point |
||||
* @return AccessToken |
||||
*/ |
||||
public static function create_temp_token($api_service = null, $duration = 60, $user_id = null, $api_end_point = null) |
||||
{ |
||||
$time = time(); |
||||
$validity_start_date = $time; |
||||
$validity_end_date = $time + $duration; |
||||
return self::create_token($user_id, $api_key = null, $api_service, $api_end_point, $validity_start_date, $validity_end_date); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param int $user_id |
||||
* @param string $api_key |
||||
* @param string $api_service |
||||
* @param string $api_end_point |
||||
* @param int $validity_start_date |
||||
* @param int $validity_end_date |
||||
* @param string $description |
||||
* @return AccessToken |
||||
*/ |
||||
public static function create_token($user_id = null, $api_key = null, $api_service = null, $api_end_point = null, $validity_start_date = null, $validity_end_date = null, $description) |
||||
{ |
||||
$time = time(); |
||||
$user_id = $user_id ? $user_id : Chamilo::user()->user_id(); |
||||
$api_key = $api_key ? $api_key : uniqid('', true); |
||||
$api_service = $api_service ? $api_service : self::default_service(); |
||||
$api_end_point = $api_end_point ? $api_end_point : ''; |
||||
$validity_start_date = $validity_start_date ? $validity_start_date : $time; |
||||
$validity_end_date = $validity_end_date ? $validity_end_date : self::end_of_time(); |
||||
$created_date = $time; |
||||
|
||||
$user_id = (int) $user_id; |
||||
$api_key = Database::escape_string($api_key); |
||||
$api_service = Database::escape_string($api_service); |
||||
$api_end_point = Database::escape_string($api_end_point); |
||||
$validity_start_date = date('Y-m-d H:i:s', $validity_start_date); |
||||
$validity_end_date = date('Y-m-d H:i:s', $validity_end_date); |
||||
$created_date = date('Y-m-d H:i:s', $created_date); |
||||
|
||||
$values = array(); |
||||
$values['user_id'] = $user_id; |
||||
$values['api_key'] = $api_key; |
||||
$values['api_service'] = $api_service; |
||||
$values['api_end_point'] = $api_end_point; |
||||
$values['validity_start_date'] = $validity_start_date; |
||||
$values['validity_end_date'] = $validity_end_date; |
||||
$values['created_date'] = $created_date; |
||||
|
||||
$table = Database::get_main_table(TABLE_MAIN_USER_API_KEY); |
||||
|
||||
$id = Database::insert($table, $values); |
||||
return AccessToken::create($id, $user_id, $api_key); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,129 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* Wrapper around pclzip. Makes a bit easier to use compression. |
||||
* |
||||
* Usage: |
||||
* |
||||
* $zip = Zip::create('...'); |
||||
* $zip->add($file_path, $local_path); |
||||
* |
||||
* Note |
||||
* |
||||
* Pclzip do not accept method callbacks. It only accepts pure function callbacks. |
||||
* As a result the implementation is a bit more complicated than it should be. |
||||
* |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
class Zip |
||||
{ |
||||
|
||||
protected static $pool = array(); |
||||
|
||||
public static function pool($hash = '') |
||||
{ |
||||
if (empty($hash)) { |
||||
return self::$pool; |
||||
} else { |
||||
return self::$pool[$hash]; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* |
||||
* @param string $path |
||||
* @return Zip |
||||
*/ |
||||
public static function create($path) |
||||
{ |
||||
return new self($path); |
||||
} |
||||
|
||||
protected $path = ''; |
||||
protected $archive = null; |
||||
protected $entries = array(); |
||||
|
||||
public function __construct($path = '') |
||||
{ |
||||
$this->path = $path; |
||||
self::$pool[$this->get_hash()] = $this; |
||||
} |
||||
|
||||
public function get_path() |
||||
{ |
||||
return $this->path; |
||||
} |
||||
|
||||
public function get_hash() |
||||
{ |
||||
return md5($this->path); |
||||
} |
||||
|
||||
public function add($file_path, $archive_path = '', $comment = '') |
||||
{ |
||||
/** |
||||
* Remove c: when working on windows. |
||||
*/ |
||||
if (substr($file_path, 1, 1) == ':') { |
||||
$file_path = substr($file_path, 2); |
||||
} |
||||
|
||||
$entry = array( |
||||
'file_path' => $file_path, |
||||
'archive_path' => $archive_path, |
||||
'comment' => $comment |
||||
); |
||||
$this->entries[$file_path] = $entry; |
||||
|
||||
$callback_name = 'zipcallback_' . $this->get_hash(); |
||||
if (!function_exists($callback_name)) { |
||||
$callback = ''; |
||||
$callback .= 'function ' . $callback_name . '($event, &$header){'; |
||||
$callback .= '$parts = explode(\'_\', __FUNCTION__);'; |
||||
$callback .= '$hash = end($parts);'; |
||||
$callback .= 'return Zip::pool($hash)->callback($event, $header);'; |
||||
$callback .= '};'; |
||||
eval($callback); |
||||
} |
||||
|
||||
$archive = $this->archive(); |
||||
$archive->add($file_path, PCLZIP_CB_PRE_ADD, $callback_name); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @return PclZip |
||||
*/ |
||||
protected function archive() |
||||
{ |
||||
if ($this->archive) { |
||||
return $this->archive; |
||||
} |
||||
if (empty($this->path)) { |
||||
return null; |
||||
} |
||||
return $this->archive = new PclZip($this->path); |
||||
} |
||||
|
||||
public function callback($event, &$header) |
||||
{ |
||||
if ($event != PCLZIP_CB_PRE_ADD) { |
||||
return 0; |
||||
} |
||||
|
||||
$path = $header['filename']; |
||||
if (!isset($this->entries[$path])) { |
||||
return 1; |
||||
} |
||||
|
||||
$entry = $this->entries[$path]; |
||||
$archive_path = $entry['archive_path']; |
||||
if (!empty($archive_path)) { |
||||
$header['stored_filename'] = $archive_path; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,6 @@ |
||||
<?php |
||||
/** |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
|
@ -0,0 +1,15 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
require_once __DIR__ . '/../inc/global.inc.php'; |
||||
|
||||
$has_access = api_protect_course_script(); |
||||
if (!$has_access) { |
||||
exit; |
||||
} |
||||
|
||||
Portfolio::controller()->run(); |
@ -0,0 +1,133 @@ |
||||
<?php |
||||
|
||||
Use Model\StudentPublication; |
||||
Use Model\Course; |
||||
|
||||
/** |
||||
* Return either |
||||
* |
||||
* - one work item (file) |
||||
* - several work items (files) zipped together |
||||
* |
||||
* Used to transfer files to another application through http. |
||||
* |
||||
* Script parameters: |
||||
* |
||||
* - id id(s) of the work item id=1 or id=1,2,4 |
||||
* - cidReq course code |
||||
* |
||||
* Note this script enables key authentication so access with a key token is possible. |
||||
* |
||||
* @package chamilo.document |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
require_once __DIR__ . '/../inc/autoload.inc.php'; |
||||
KeyAuth::enable(); |
||||
|
||||
require_once __DIR__ . '/../inc/global.inc.php'; |
||||
|
||||
$has_access = api_protect_course_script(); |
||||
if (!$has_access) { |
||||
exit; |
||||
} |
||||
|
||||
session_cache_limiter('none'); |
||||
|
||||
$ids = Request::get('id', ''); |
||||
$ids = $ids ? explode(',', $ids) : array(); |
||||
|
||||
$course = Course::current(); |
||||
|
||||
/** |
||||
* No files requested. We make sure we return 404 error to tell the client |
||||
* that the call failed. |
||||
*/ |
||||
if (count($ids) == 0 || empty($course)) { |
||||
Response::not_found(); |
||||
} |
||||
|
||||
/** |
||||
* One file/folder requested. |
||||
*/ |
||||
if (count($ids) == 1) { |
||||
$id = reset($ids); |
||||
$pub = StudentPublication::get_by_id($course, $id); |
||||
if (empty($pub)) { |
||||
Response::not_found(); |
||||
} |
||||
|
||||
$has_access = $pub->is_accessible(); |
||||
if (!$has_access) { |
||||
Response::not_found(); |
||||
} |
||||
|
||||
if ($pub->is_file()) { |
||||
event_download(Uri::here()); |
||||
DocumentManager::file_send_for_download($pub->get_absolute_path(), false, $pub->get_title()); |
||||
exit; |
||||
} |
||||
|
||||
/** |
||||
* one folder requested |
||||
*/ |
||||
$items = array(); |
||||
$children = $pub->get_children(); |
||||
foreach ($children as $child) { |
||||
if ($child->is_accessible()) { |
||||
$items[] = $child; |
||||
} |
||||
} |
||||
if (count($items) == 0) { |
||||
Response::not_found(); |
||||
} |
||||
|
||||
$zip = Chamilo::temp_zip(); |
||||
foreach ($items as $item) { |
||||
$path = $item->get_absolute_path(); |
||||
$title = $item->get_title(); |
||||
$zip->add($path, $title); |
||||
} |
||||
event_download(Uri::here()); |
||||
DocumentManager::file_send_for_download($zip->get_path(), false, $pub->get_title() . '.zip'); |
||||
} |
||||
|
||||
/** |
||||
* Several files requested. In this case we zip them together. |
||||
*/ |
||||
$items = array(); |
||||
foreach ($ids as $id) { |
||||
$pub = StudentPublication::get_by_id($course, $id); |
||||
if (!$pub->is_accessible()) { |
||||
break; |
||||
} |
||||
if ($pub->is_file()) { |
||||
$items[] = $pub; |
||||
} |
||||
/** |
||||
* We ignore folders |
||||
*/ |
||||
} |
||||
|
||||
/** |
||||
* Requested files may not be accessible. |
||||
*/ |
||||
if (count($items) == 0) { |
||||
Response::not_found(); |
||||
} |
||||
|
||||
/** |
||||
* Zip files together. |
||||
*/ |
||||
$zip = Chamilo::temp_zip(); |
||||
foreach ($items as $item) { |
||||
$path = $item->get_absolute_path(); |
||||
$title = $item->get_title(); |
||||
$zip->add($path, $title); |
||||
} |
||||
|
||||
/** |
||||
* Send file for download |
||||
*/ |
||||
event_download(Uri::here()); |
||||
DocumentManager::file_send_for_download($zip->get_path(), false, get_lang('StudentPublications') . '.zip'); |
Loading…
Reference in new issue