#2851 portfolio integration

skala
Laurent Opprecht 13 years ago
parent db83ff5706
commit bffe3f6015
  1. 199
      main/auth/key/key_auth.class.php
  2. 1
      main/auth/key/login.php
  3. 6
      main/document/document.inc.php
  4. 965
      main/document/document.php
  5. 154
      main/document/file.php
  6. BIN
      main/img/icons/22/document_send.png
  7. 2
      main/inc/conf/course_info.conf.dist.php
  8. 185
      main/inc/lib/access_token.class.php
  9. 24
      main/inc/lib/autoload.class.php
  10. 39
      main/inc/lib/chamilo.class.php
  11. 145
      main/inc/lib/course.class.php
  12. 302
      main/inc/lib/document.class.php
  13. 2
      main/inc/lib/export.lib.inc.php
  14. 32
      main/inc/lib/header.class.php
  15. 251
      main/inc/lib/item_property.class.php
  16. 4
      main/inc/lib/javascript/jqgrid/css/ui.jqgrid.css
  17. 66
      main/inc/lib/login.lib.php
  18. 3
      main/inc/lib/main_api.lib.php
  19. 642
      main/inc/lib/portfolio.class.php
  20. 23
      main/inc/lib/response.class.php
  21. 33
      main/inc/lib/result_set.class.php
  22. 439
      main/inc/lib/student_publication.class.php
  23. 145
      main/inc/lib/system/io/temp.class.php
  24. 131
      main/inc/lib/system/net/curl.class.php
  25. 72
      main/inc/lib/system/net/http_channel.class.php
  26. 149
      main/inc/lib/system/portfolio/artefact.class.php
  27. 35
      main/inc/lib/system/portfolio/download.class.php
  28. 52
      main/inc/lib/system/portfolio/mahara.class.php
  29. 106
      main/inc/lib/system/portfolio/portfolio.class.php
  30. 19
      main/inc/lib/system/portfolio/user.class.php
  31. 81
      main/inc/lib/system/web/header.class.php
  32. 6
      main/inc/lib/system/web/request.class.php
  33. 0
      main/inc/lib/system/web/request_server.class.php
  34. 103
      main/inc/lib/user_api_key_manager.class.php
  35. 2
      main/inc/lib/usermanager.lib.php
  36. 129
      main/inc/lib/zip.class.php
  37. 1
      main/install/configuration.dist.php
  38. 1
      main/install/install_files.inc.php
  39. 86
      main/install/update-files-1.8.8-1.9.0.inc.php
  40. 6
      main/portfolio/index.php
  41. 15
      main/portfolio/share.php
  42. 133
      main/work/file.php
  43. 6
      main/work/work.lib.php

@ -2,18 +2,11 @@
use \ChamiloSession as Session;
/**
* Used to authenticate user with an access token. By default this method is disabled.
* Method used primarily to make API calls:Rss, etc.
*
* Access is granted only for the services that are enabled.
*
* You need to call
*
* KeyAuth::enable_services('my_service');
* Method used primarily to make API calls: Rss, file upload.
*
* to enable this access method for a specific service before a call to global.inc.php.
* Access is granted only for the services that are enabled.
*
* To be secured this method must
*
@ -23,15 +16,40 @@ use \ChamiloSession as Session;
* This authentication method is session less. This is to ensure that the navigator
* do not receive an access cookie that will grant it access to other parts of the
* application.
*
*
*
* Usage:
*
* Enable KeyAuth for a specific service. Add the following lines so that
* the key authentication method is enabled for a specific service before
* calling global.inc.php.
*
* include_once '.../main/inc/autoload.inc.php';
* KeyAuth::enable_services('my_service');
* include_once '.../main/inc/global.inc.php';
*
*
* Enable url access for a short period of time:
*
* token = KeyAuth::create_temp_token();
* url = '...?access_token=' . $token ;
*
* @see AccessToken
* @license see /license.txt
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva
*/
class KeyAuth
{
const PARAM_ACCESS_TOKEN = 'access_token';
protected static $services = array();
public static function create_temp_token($service = null, $duration = 60, $user_id = null)
{
return UserApiKeyManager::create_temp_token($service, $duration, $user_id);
}
/**
* Returns enabled services
*
@ -52,15 +70,11 @@ class KeyAuth
{
$args = func_get_args();
$names = array();
foreach ($args as $arg)
{
if (is_object($arg))
{
foreach ($args as $arg) {
if (is_object($arg)) {
$f = array($arg, 'get_service_name');
$name = call_user_func($f);
}
else
{
} else {
$name = $arg;
}
$name = substr($name, 0, 10);
@ -72,20 +86,46 @@ class KeyAuth
{
$args = func_get_args();
$names = array();
foreach ($args as $name)
{
foreach ($args as $name) {
$name = substr($name, 0, 10);
unset(self::$services[$name]);
}
}
public static function is_service_enabled($service)
{
$services = self::get_services();
foreach ($services as $s) {
if ($s == $service) {
return true;
}
}
return false;
}
public static function clear_services()
{
self::$services[$name] = array();
}
/**
* Enable key authentication for the default service - i.e. chamilo
*/
public static function enable()
{
self::enable_services(UserApiKeyManager::default_service());
}
public static function disable()
{
self::$services[$name] = array();
}
/**
* @return Returns true if authentication method is enabled. False otherwise.
* Returns true if the key authentication method is enabled. False otherwise.
* Default to false.
*
* @return bool
*/
public static function is_enabled()
{
@ -98,8 +138,7 @@ class KeyAuth
public static function instance()
{
static $result = null;
if(empty($result))
{
if (empty($result)) {
$result = new self();
}
return $result;
@ -111,60 +150,52 @@ class KeyAuth
}
/**
* Returns true if security accepts to run otherwise returns false.
* Returns true if authentication accepts to run otherwise returns false.
*
* @return boolean
*/
public function accept()
{
$user_id = $this->get_user_id();
if (empty($user_id))
{
/**
* Authentication method must be enabled
*/
if (!self::is_enabled()) {
return false;
}
$services = $this->get_services();
if (empty($services))
{
$token = $this->get_access_token();
if ($token->is_empty()) {
return false;
}
$token = $this->get_token();
if (empty($token))
{
$key = UserApiKeyManager::get_by_id($token->get_id());
if (empty($key)) {
return false;
}
// $control = $this->get_control();
// if (empty($control))
// {
// return false;
// }
$user = UserManager::get_user_info_by_id($user_id);
if (empty($user))
{
/**
* The service corresponding to the key must be enabled.
*/
$service = $key['api_service'];
if (!self::is_service_enabled($service)) {
return false;
}
if ($user['active'] != 1)
{
/**
* User associated with the key must be active
*/
$user = UserManager::get_user_info_by_id($token->get_user_id());
if (empty($user)) {
return false;
}
foreach ($services as $service)
{
$keys = UserManager::get_api_keys($user_id, $service);
$keys = $keys ? $keys : array();
foreach ($keys as $key)
{
if ($key == $token)
{
return true;
}
}
if (!$user['active']) {
return false;
}
return false;
/**
* Token must be valid.
*/
return $token->is_valid();
}
/**
@ -175,8 +206,7 @@ class KeyAuth
*/
public function login()
{
if (!$this->accept())
{
if (!$this->accept()) {
return false;
}
/**
@ -184,52 +214,49 @@ class KeyAuth
*/
Session::destroy();
global $_user, $_uid;
$_uid = $this->get_user_id();
$_user = UserManager::get_user_info_by_id($_uid);
Session::write('_user',$_user);
Session::write('_uid',$_uid);
/**
* We don't allow redirection since access is granted only for this call
*/
global $no_redirection, $noredirection;
$no_redirection = true;
$noredirection = true;
Session::write('noredirection',$noredirection);
Session::write('noredirection', $noredirection);
$user_id = $this->get_user_id();
$course_code = $this->get_course_code();
$group_id = $this->get_group_id();
Login::init_user($user_id, true);
Login::init_course($course_code, true);
Login::init_group($group_id, true);
return true;
}
/**
* Returns the request user id parameter
* Returns the request access token
*
* @return int
* @return AccessToken
*/
public function get_access_token()
{
$string = Request::get(self::PARAM_ACCESS_TOKEN);
return AccessToken::parse($string);
}
public function get_user_id()
{
return (int) Request::get('user_id');
return $this->get_access_token()->get_user_id();
}
/**
* Returns the request security token parameter
*
* @return string
*/
public function get_token()
public function get_course_code()
{
return Request::get('token');
return Request::get('cidReq', 0);
}
/**
* Returns the control token parameter
*
* @return string
*/
public function get_control()
public function get_group_id()
{
return Request::get('control');
return Request::get('gidReq', 0);
}
}

@ -223,9 +223,9 @@ function create_document_link($document_data, $show_as_icon = false, $counter =
$copy_to_myfiles = '<a href="'.$copy_myfiles_link.'" style="float:right"'.$prevent_multiple_click.'>'.Display::return_icon('briefcase.png', get_lang('CopyToMyFiles'), array(),ICON_SIZE_SMALL).'&nbsp;&nbsp;</a>';
}
$send_to = '';
// if ($filetype == 'file') {
// $send_to = Portfolio::share($document_data['id'], array('style' => 'float:right;'));
// }
if ($filetype == 'file') {
$send_to = Portfolio::share('document', $document_data['id'], array('style' => 'float:right;'));
}
}
$pdf_icon = '';

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');

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -41,5 +41,3 @@ $canReportExpirationDate = true; // Needs to be true
// is not automaticly called
//$linkToChangeDiskQuota = 'changeQuota.php';
$urlScriptToReportExpirationDate = 'postpone.php'; // external script to postpone the expiration of course.
?>

@ -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;
}
}

@ -56,6 +56,7 @@ class Autoload
*/
$result = array();
$result['AbstractLink'] = '/main/gradebook/lib/be/abstractlink.class.php';
$result['AccessToken'] = '/main/inc/lib/access_token.class.php';
$result['Accessurleditcoursestourl'] = '/main/inc/lib/access_url_edit_courses_to_url_functions.lib.php';
$result['Accessurleditsessionstourl'] = '/main/inc/lib/access_url_edit_sessions_to_url_functions.lib.php';
$result['Accessurledituserstourl'] = '/main/inc/lib/access_url_edit_users_to_url_functions.lib.php';
@ -152,9 +153,6 @@ class Autoload
$result['FillBlanks'] = '/main/exercice/fill_blanks.class.php';
$result['FlatViewDataGenerator'] = '/main/gradebook/lib/flatview_data_generator.class.php';
$result['FlatViewTable'] = '/main/gradebook/lib/fe/flatviewtable.class.php';
$result['FormElement'] = '/main/media/lib/form_element.class.php';
$result['FormElementTextarea'] = '/main/media/lib/form_element_textarea.class.php';
$result['FormRule'] = '/main/media/lib/form_rule.class.php';
$result['FormValidator'] = '/main/inc/lib/formvalidator/FormValidator.class.php';
$result['Forum'] = '/main/coursecopy/classes/Forum.class.php';
$result['ForumCategory'] = '/main/coursecopy/classes/ForumCategory.class.php';
@ -235,7 +233,7 @@ class Autoload
$result['HTML_QuickForm_xbutton'] = '/main/inc/lib/pear/HTML/QuickForm/xbutton.php';
$result['HTML_Table'] = '/main/inc/lib/pear/HTML/Table.php';
$result['HTML_Table_Storage'] = '/main/inc/lib/pear/HTML/Table/Storage.php';
$result['Header'] = '/main/inc/lib/header.class.php';
$result['Header'] = '/main/inc/lib/system/web/header.class.php';
$result['HotSpot'] = '/main/exercice/hotspot.class.php';
$result['HotSpotDelineation'] = '/main/exercice/hotspot.class.php';
$result['Html'] = '/main/inc/lib/html.class.php';
@ -261,9 +259,11 @@ class Autoload
$result['Login'] = '/main/inc/lib/login.lib.php';
$result['LoginRedirection'] = '/main/inc/lib/login_redirection.class.php';
$result['Matching'] = '/main/exercice/matching.class.php';
$result['Media'] = '/main/media/model/media.class.php';
$result['MediaForm'] = '/main/media/lib/media_form.class.php';
$result['MessageManager'] = '/main/inc/lib/message.lib.php';
$result['Model\Course'] = '/main/inc/lib/course.class.php';
$result['Model\Document'] = '/main/inc/lib/document.class.php';
$result['Model\ItemProperty'] = '/main/inc/lib/item_property.class.php';
$result['Model\StudentPublication'] = '/main/inc/lib/student_publication.class.php';
$result['MultipleAnswer'] = '/main/exercice/multiple_answer.class.php';
$result['MultipleAnswerCombination'] = '/main/exercice/multiple_answer_combination.class.php';
$result['MultipleAnswerCombinationTrueFalse'] = '/main/exercice/multiple_answer_combination_true_false.class.php';
@ -271,8 +271,6 @@ class Autoload
$result['MyHorBar'] = '/main/inc/lib/pchart/MyHorBar.class.php';
$result['MySpace'] = '/main/mySpace/myspace.lib.php';
$result['Nanogong'] = '/main/inc/lib/nanogong.lib.php';
$result['NetworkCredential'] = '/main/inc/lib/system/net/network_credential.class.php';
$result['NewMediaForm'] = '/main/media/lib/new_media_form.class.php';
$result['NotebookManager'] = '/main/inc/lib/notebook.lib.php';
$result['Notification'] = '/main/inc/lib/notification.lib.php';
$result['OLE'] = '/main/inc/lib/pear/OLE/OLE.php';
@ -298,9 +296,11 @@ class Autoload
$result['PclZip'] = '/main/inc/lib/pclzip/pclzip.lib.php';
$result['Plugin'] = '/main/inc/lib/plugin.class.php';
$result['Portfolio'] = '/main/inc/lib/portfolio.class.php';
$result['PortfolioBulkAction'] = '/main/inc/lib/portfolio.class.php';
$result['PortfolioController'] = '/main/inc/lib/portfolio.class.php';
$result['PortfolioShare'] = '/main/inc/lib/portfolio.class.php';
$result['Portfolio\Artefact'] = '/main/inc/lib/system/portfolio/artefact.class.php';
$result['Portfolio\Download'] = '/main/inc/lib/system/portfolio/download.class.php';
$result['Portfolio\Mahara'] = '/main/inc/lib/system/portfolio/mahara.class.php';
$result['Portfolio\Portfolio'] = '/main/inc/lib/system/portfolio/portfolio.class.php';
$result['Portfolio\User'] = '/main/inc/lib/system/portfolio/user.class.php';
@ -313,8 +313,8 @@ class Autoload
$result['Quiz'] = '/main/coursecopy/classes/Quiz.class.php';
$result['QuizQuestion'] = '/main/coursecopy/classes/QuizQuestion.class.php';
$result['Redirect'] = '/main/inc/lib/redirect.class.php';
$result['Request'] = '/main/inc/lib/request.class.php';
$result['RequestServer'] = '/main/inc/lib/request_server.class.php';
$result['Request'] = '/main/inc/lib/system/web/request.class.php';
$result['RequestServer'] = '/main/inc/lib/system/web/request_server.class.php';
$result['Resource'] = '/main/coursecopy/classes/Resource.class.php';
$result['Result'] = '/main/gradebook/lib/be/result.class.php';
$result['ResultSet'] = '/main/inc/lib/result_set.class.php';
@ -370,6 +370,7 @@ class Autoload
$result['SystemAnnouncementManager'] = '/main/inc/lib/system_announcements.lib.php';
$result['System\Session'] = '/main/inc/lib/system/session.class.php';
$result['TableSort'] = '/main/inc/lib/table_sort.class.php';
$result['Temp'] = '/main/inc/lib/system/io/temp.class.php';
$result['Template'] = '/main/inc/lib/template.lib.php';
$result['Text_Diff'] = '/main/inc/lib/pear/Text/Diff.php';
$result['Text_Diff3'] = '/main/inc/lib/pear/Text/Diff3.php';
@ -406,6 +407,7 @@ class Autoload
$result['Uri'] = '/main/inc/lib/uri.class.php';
$result['UrlManager'] = '/main/inc/lib/urlmanager.lib.php';
$result['User'] = '/main/auth/shibboleth/app/model/user.class.php';
$result['UserApiKeyManager'] = '/main/inc/lib/user_api_key_manager.class.php';
$result['UserDataGenerator'] = '/main/gradebook/lib/user_data_generator.class.php';
$result['UserForm'] = '/main/gradebook/lib/fe/userform.class.php';
$result['UserGroup'] = '/main/inc/lib/usergroup.lib.php';
@ -417,6 +419,7 @@ class Autoload
$result['Utf8Encoder'] = '/main/inc/lib/system/text/utf8_encoder.class.php';
$result['Wiki'] = '/main/coursecopy/classes/wiki.class.php';
$result['XapianIndexer'] = '/main/inc/lib/search/xapian/XapianIndexer.class.php';
$result['Zip'] = '/main/inc/lib/zip.class.php';
$result['ZombieManager'] = '/main/inc/lib/zombie/zombie_manager.class.php';
$result['ZombieReport'] = '/main/inc/lib/zombie/zombie_report.class.php';
$result['_Admin'] = '/main/auth/shibboleth/app/model/scaffold/admin.class.php';
@ -445,6 +448,7 @@ class Autoload
$result['db'] = '/main/inc/lib/db.lib.php';
$result['document_processor'] = '/main/inc/lib/search/tool_processors/document_processor.class.php';
$result['iDatabase'] = '/main/install/i_database.class.php';
$result['langstats'] = '/main/cron/lang/langstats.class.php';
$result['learnpath'] = '/main/newscorm/learnpath.class.php';
$result['learnpathItem'] = '/main/newscorm/learnpathItem.class.php';
$result['learnpathList'] = '/main/newscorm/learnpathList.class.php';

@ -42,7 +42,7 @@ class Chamilo
{
return ChamiloSession::instance();
}
/**
*
* @return CurrentUser
@ -93,10 +93,43 @@ class Chamilo
return api_get_path(SYS_COURSE_PATH);
}
public static function temp($ext = '')
/**
* Returns a temporary file - one that is automatically deleted at the end
* of the script.
*
* @param string $ext
* @return Temp
*/
public static function temp_file($ext = '')
{
$ext = $ext ? '.' . $ext : '';
return api_get_path(SYS_ARCHIVE_PATH) . uniqid() . $ext;
Temp::set_temp_root(api_get_path(SYS_ARCHIVE_PATH) . 'temp');
$path = Temp::get_temporary_name() . $ext;
return Temp::create($path);
}
/**
* Returns a temporary directory - one that is automatically deleted at the end
* of the script.
*
* @param string $ext
* @return Temp
*/
public static function temp_dir()
{
$ext = $ext ? '.' . $ext : '';
Temp::set_temp_root(api_get_path(SYS_ARCHIVE_PATH) . 'temp');
$path = Temp::get_temporary_name() . $ext;
return Temp::dir($path);
}
/**
*
* @return Zip
*/
public static function temp_zip()
{
return Zip::create(self::temp_file('zip'));
}
public static function path($path = '')

@ -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);
}
}

@ -57,7 +57,7 @@ class Export {
if(empty($data)){
return false;
}
$path = Chamilo::temp();
$path = Chamilo::temp_file();
$converter = new Utf8Encoder(null, true);
$file = FileWriter::create($path, $converter);
$file = CsvWriter::create($file);

@ -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;
}
}

@ -29,11 +29,11 @@
tr.ui-search-toolbar input {margin: 1px 0px 0px 0px}
tr.ui-search-toolbar select {margin: 1px 0px 0px 0px}
/* body */
.ui-jqgrid .ui-jqgrid-bdiv {position: relative; margin: 0em; padding:0; overflow: auto; text-align:left;}
.ui-jqgrid .ui-jqgrid-bdiv {position: relative; margin: 0em; padding:0; overflow: visible; text-align:left;}
.ui-jqgrid .ui-jqgrid-btable {table-layout:fixed; margin:0em; outline-style: none; }
.ui-jqgrid tr.jqgrow { outline-style: none; }
.ui-jqgrid tr.jqgroup { outline-style: none; }
.ui-jqgrid tr.jqgrow td {font-weight: normal; overflow: hidden; white-space: pre; height: 22px;padding: 0 2px 0 2px;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}
.ui-jqgrid tr.jqgrow td {font-weight: normal; overflow: visible; white-space: pre; height: 22px;padding: 0 2px 0 2px;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}
.ui-jqgrid tr.jqgfirstrow td {padding: 0 2px 0 2px;border-right-width: 1px; border-right-style: solid;}
.ui-jqgrid tr.jqgroup td {font-weight: normal; overflow: hidden; white-space: pre; height: 22px;padding: 0 2px 0 2px;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}
.ui-jqgrid tr.jqfoot td {font-weight: bold; overflow: hidden; white-space: pre; height: 22px;padding: 0 2px 0 2px;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}

@ -2,7 +2,6 @@
use \ChamiloSession as Session;
/* For licensing terms, see /license.txt */
/**
* Code library for login process
@ -262,20 +261,22 @@ class Login
$is_allowedCreateCourse = (bool) (($uData ['status'] == 1) or (api_get_setting('drhCourseManagerRights') and $uData['status'] == 4));
ConditionalLogin::check_conditions($uData);
Session::write('_user',$_user);
Session::write('_user', $_user);
UserManager::update_extra_field_value($_user['user_id'], 'already_logged_in', 'true');
Session::write('is_platformAdmin',$is_platformAdmin);
Session::write('is_allowedCreateCourse',$is_allowedCreateCourse);
// If request_uri is setted we have to go further to have course permissions
if (empty($_SESSION['request_uri']) || !isset($_SESSION['request_uri'])) {
if (isset($_SESSION['noredirection'])) {
//If we just want to reset info without redirecting user
unset($_SESSION['noredirection']);
} else {
LoginRedirection::redirect();
}
}
Session::write('is_platformAdmin', $is_platformAdmin);
Session::write('is_allowedCreateCourse', $is_allowedCreateCourse);
//
//
// // If request_uri is setted we have to go further to have course permissions
// if (empty($_SESSION['request_uri']) || !isset($_SESSION['request_uri'])) {
// if (isset($_SESSION['noredirection'])) {
// //If we just want to reset info without redirecting user
// unset($_SESSION['noredirection']);
// } else {
// LoginRedirection::redirect();
// }
// }
} else {
header('location:' . api_get_path(WEB_PATH));
//exit("WARNING UNDEFINED UID !! ");
@ -285,8 +286,8 @@ class Login
Session::erase('_uid');
}
Session::write('is_platformAdmin',$is_platformAdmin);
Session::write('is_allowedCreateCourse',$is_allowedCreateCourse);
Session::write('is_platformAdmin', $is_platformAdmin);
Session::write('is_allowedCreateCourse', $is_allowedCreateCourse);
} else { // continue with the previous values
$_user = $_SESSION['_user'];
$is_platformAdmin = $_SESSION['is_platformAdmin'];
@ -315,6 +316,7 @@ class Login
*/
static function init_course($course_id, $reset)
{
global $_configuration;
global $is_platformAdmin;
global $is_allowedCreateCourse;
global $_user;
@ -331,7 +333,7 @@ class Login
global $is_sessionAdmin;
global $is_allowed_in_course;
if (isset($reset) && $reset) {
if ($reset) {
// Course session data refresh requested or empty data
if ($course_id) {
$course_table = Database::get_main_table(TABLE_MAIN_COURSE);
@ -373,11 +375,11 @@ class Login
$_course['activate_legal'] = $course_data['activate_legal'];
$_course['show_score'] = $course_data['show_score']; //used in the work tool
Session::write('_cid',$_cid);
Session::write('_course',$_course);
Session::write('_cid', $_cid);
Session::write('_course', $_course);
//@TODO real_cid should be cid, for working with numeric course id
Session::write('_real_cid',$_real_cid);
Session::write('_real_cid', $_real_cid);
// if a session id has been given in url, we store the session
if (api_get_setting('use_session_mode') == 'true') {
@ -520,7 +522,7 @@ class Login
//Course - User permissions
$is_sessionAdmin = false;
if ((isset($uidReset) && $uidReset) || (isset($cidReset) && $cidReset)) {
if ($reset) {
if (isset($user_id) && $user_id && isset($_cid) && $_cid) {
@ -528,7 +530,7 @@ class Login
$course_user_table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
$sql = "SELECT * FROM $course_user_table
WHERE user_id = '" . $user_id . "' AND relation_type <> " . COURSE_RELATION_TYPE_RRHH . "
AND course_code = '$cidReq'";
AND course_code = '$course_id'";
$result = Database::query($sql);
$cuData = null;
@ -548,7 +550,7 @@ class Login
}
}
$_courseUser['role'] = $cuData['role'];
Session::write('_courseUser',$_courseUser);
Session::write('_courseUser', $_courseUser);
}
//We are in a session course? Check session permissions
@ -610,14 +612,14 @@ class Login
} else {
$is_courseAdmin = false;
}
Session::write('_courseUser',$_courseUser);
Session::write('_courseUser', $_courseUser);
break;
case '0': //student
$is_courseMember = true;
$is_courseTutor = false;
$is_courseAdmin = false;
$is_sessionAdmin = false;
Session::write('_courseUser',$_courseUser);
Session::write('_courseUser', $_courseUser);
break;
default:
//unregister user
@ -701,13 +703,13 @@ class Login
}
// save the states
Session::write('is_courseAdmin',$is_courseAdmin);
Session::write('is_courseMember',$is_courseMember);
Session::write('is_courseTutor',$is_courseTutor);
Session::write('is_courseCoach',$is_courseCoach);
Session::write('is_allowed_in_course',$is_allowed_in_course);
Session::write('is_courseAdmin', $is_courseAdmin);
Session::write('is_courseMember', $is_courseMember);
Session::write('is_courseTutor', $is_courseTutor);
Session::write('is_courseCoach', $is_courseCoach);
Session::write('is_allowed_in_course', $is_allowed_in_course);
Session::write('is_sessionAdmin',$is_sessionAdmin);
Session::write('is_sessionAdmin', $is_sessionAdmin);
} else { // continue with the previous values
if (isset($_SESSION ['_courseUser'])) {
$_courseUser = $_SESSION ['_courseUser'];
@ -744,7 +746,7 @@ class Login
if (Database::num_rows($result) > 0) { // This group has recorded status related to this course
$gpData = Database::fetch_array($result);
$_gid = $gpData ['id'];
Session::write('_gid',$_gid);
Session::write('_gid', $_gid);
} else {
Session::erase('_gid');
}

@ -2680,7 +2680,8 @@ function api_not_found($print_headers = false) {
* @version dokeos 1.8, August 2006
*/
function api_not_allowed($print_headers = false, $message = null) {
Header::response_code(403);
$home_url = api_get_path(WEB_PATH);
$user = api_get_user_id(); //0 if not defined
$course = api_get_course_id();

@ -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;
}
}

@ -28,14 +28,16 @@ class ResultSet implements Countable, Iterator
protected $limit_offset = null;
protected $orderby_column = null;
protected $orderby_direction = null;
protected $return_type = null;
function __construct($sql, $limit_count = null, $limit_offset = null, $orderby_column = null, $orderby_direction = null)
function __construct($sql, $limit_count = null, $limit_offset = null, $orderby_column = null, $orderby_direction = null, $return_type = null)
{
$this->sql = $sql;
$this->limit_count = $limit_count;
$this->limit_offset = $limit_offset;
$this->orderby_column = $orderby_column;
$this->orderby_direction = $direction;
$this->return_type = $return_type;
}
public function sql()
@ -53,8 +55,7 @@ class ResultSet implements Countable, Iterator
if (strpos($sql, ' ORDER ') || strpos($sql, ' LIMIT ') || strpos($sql, ' OFFSET ')) {
$sql = "SELECT * FROM ($sql) AS dat ";
}else
{
} else {
$sql .= ' ';
}
@ -94,6 +95,14 @@ class ResultSet implements Countable, Iterator
return $this->count;
}
public function first()
{
foreach ($this as $item) {
return $item;
}
return null;
}
/**
*
* @param int $count
@ -122,6 +131,13 @@ class ResultSet implements Countable, Iterator
return $result;
}
public function return_type($value)
{
$result = clone($this);
$result->return_type = $value;
return $result;
}
public function current()
{
return $this->current;
@ -134,7 +150,16 @@ class ResultSet implements Countable, Iterator
public function next()
{
$this->current = Database::fetch_assoc($this->handle());
$data = Database::fetch_assoc($this->handle());
if (!$data) {
$this->current = $this->return_type ? null : array();
} else if (empty($this->return_type)) {
$this->current = $data;
} else if ($this->return_type == 'object') {
$this->current = (object) $data;
} else {
$this->current = new $this->return_type($data);
}
$this->index++;
return $this->current;
}

@ -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);
}
}

@ -11,7 +11,11 @@ class Request
public static function get($key, $default = null)
{
return isset($_GET[$key]) ? $_GET[$key] : $default;
return isset($_REQUEST[$key]) ? $_REQUEST[$key] : $default;
}
public static function has($key){
return isset($_REQUEST[$key]);
}
/**

@ -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);
}
}

@ -2253,7 +2253,7 @@ class UserManager {
$service_name = Database::escape_string($api_service);
if (is_string($service_name) === false) { return false;}
$t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY);
$sql = "SELECT id, api_key FROM $t_api WHERE user_id = ".$user_id." AND api_service='".$api_service."';";
$sql = "SELECT * FROM $t_api WHERE user_id = $user_id AND api_service='$api_service';";
$res = Database::query($sql);
if ($res === false) return false; //error during query
$num = Database::num_rows($res);

@ -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;
}
}

@ -165,4 +165,3 @@ $_configuration['deny_delete_users'] = false;
// Version settings
$_configuration['system_version'] = '{NEW_VERSION}';
$_configuration['system_stable'] = NEW_VERSION_STABLE;
?>

@ -30,6 +30,7 @@ if (defined('SYSTEM_INSTALLATION')) {
copy(api_get_path(CONFIGURATION_PATH).'course_info.conf.dist.php', api_get_path(CONFIGURATION_PATH).'course_info.conf.php');
copy(api_get_path(CONFIGURATION_PATH).'mail.conf.dist.php', api_get_path(CONFIGURATION_PATH).'mail.conf.php');
copy(api_get_path(CONFIGURATION_PATH).'profile.conf.dist.php', api_get_path(CONFIGURATION_PATH).'profile.conf.php');
copy(api_get_path(CONFIGURATION_PATH).'portfolio.conf.dist.php', api_get_path(CONFIGURATION_PATH).'portfolio.conf.php');
} else {
echo 'You are not allowed here !';
}

@ -1,4 +1,5 @@
<?php
/* For licensing terms, see /license.txt */
/**
@ -10,44 +11,51 @@
* current configuration file.
* @package chamilo.install
*/
Log::notice('Entering file');
if (defined('SYSTEM_INSTALLATION')) {
// Edit the configuration file
$file = file(api_get_path(CONFIGURATION_PATH).'configuration.php');
$fh = fopen(api_get_path(CONFIGURATION_PATH).'configuration.php', 'w');
$found_version_old = false;
$found_stable_old = false;
$found_version = false;
$found_stable = false;
$found_software_name = false;
$found_software_url = false;
foreach ($file as $line) {
$ignore = false;
if (stripos($line,'$userPasswordCrypted') !== false) {
$line = '$_configuration[\'password_encryption\'] = \''.($userPasswordCrypted).'\';'."\r\n";
} elseif (stripos($line, '?>') !== false) {
$ignore = true;
}
if (!$ignore) {
fwrite($fh, $line);
}
}
if (!$found_version) {
fwrite($fh, '$_configuration[\'system_version\'] = \''.$new_version.'\';'."\r\n");
}
if (!$found_stable) {
fwrite($fh, '$_configuration[\'system_stable\'] = '.($new_version_stable?'true':'false').';'."\r\n");
}
if (!$found_software_name) {
fwrite($fh, '$_configuration[\'software_name\'] = \''.$software_name.'\';'."\r\n");
}
if (!$found_software_url) {
fwrite($fh, '$_configuration[\'software_url\'] = \''.$software_url.'\';'."\r\n");
}
$string = <<<EOP
$conf_dir = api_get_path(CONFIGURATION_PATH);
$portfolio_conf_dist = $conf_dir . 'portfolio.conf.dist.php';
$portfolio_conf = $conf_dir . 'portfolio.conf.dist.php';
if (!file_exists($portfolio_conf)) {
copy($portfolio_conf_dist, $portfolio_conf);
}
// Edit the configuration file
$file = file(api_get_path(CONFIGURATION_PATH) . 'configuration.php');
$fh = fopen(api_get_path(CONFIGURATION_PATH) . 'configuration.php', 'w');
$found_version_old = false;
$found_stable_old = false;
$found_version = false;
$found_stable = false;
$found_software_name = false;
$found_software_url = false;
foreach ($file as $line) {
$ignore = false;
if (stripos($line, '$userPasswordCrypted') !== false) {
$line = '$_configuration[\'password_encryption\'] = \'' . ($userPasswordCrypted) . '\';' . "\r\n";
} elseif (stripos($line, '?>') !== false) {
$ignore = true;
}
if (!$ignore) {
fwrite($fh, $line);
}
}
if (!$found_version) {
fwrite($fh, '$_configuration[\'system_version\'] = \'' . $new_version . '\';' . "\r\n");
}
if (!$found_stable) {
fwrite($fh, '$_configuration[\'system_stable\'] = ' . ($new_version_stable ? 'true' : 'false') . ';' . "\r\n");
}
if (!$found_software_name) {
fwrite($fh, '$_configuration[\'software_name\'] = \'' . $software_name . '\';' . "\r\n");
}
if (!$found_software_url) {
fwrite($fh, '$_configuration[\'software_url\'] = \'' . $software_url . '\';' . "\r\n");
}
$string = <<<EOP
//============================================================================
// Hosting settings - Allows you to set limits to the Chamilo portal when
// hosting it for a third party. These settings can be overwritten by an
@ -65,12 +73,10 @@ $_configuration['hosting_limit_sessions'] = 0;
// Default (0) = no limit
$_configuration['hosting_limit_disk_space'] = 0;
EOP;
fwrite($fh,$string);
fwrite($fh, '?>');
fclose($fh);
fwrite($fh, $string);
fwrite($fh, '?>');
fclose($fh);
} else {
echo 'You are not allowed here !';
echo 'You are not allowed here !';
}

@ -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');

@ -1660,7 +1660,9 @@ function get_work_user_list($start, $limit, $column, $direction, $work_id, $wher
$link_to_download = '<a href="download.php?id='.$item_id.'">'.Display::return_icon('save.png', get_lang('Save'),array(), ICON_SIZE_SMALL).'</a> ';
} else {
$link_to_download = '<a href="view.php?id='.$item_id.'">'.Display::return_icon('default.png', get_lang('View'),array(), ICON_SIZE_SMALL).'</a> ';
}
}
$send_to = Portfolio::share('work', $work['id'], array('style' => 'white-space:nowrap;'));
$work['qualification'] = $qualification_string;
@ -1724,7 +1726,7 @@ function get_work_user_list($start, $limit, $column, $direction, $work_id, $wher
$qualificator_id = Display::label(get_lang('Revised'), 'success');
}
$work['qualificator_id'] = $qualificator_id;
$work['actions'] = $link_to_download.$action;
$work['actions'] = $send_to.$link_to_download.$action;
$works[] = $work;
}
}

Loading…
Cancel
Save