Beispiel #1
0
 /**
  * Create method for this handler
  *
  * @return array of assets created
  **/
 public function create()
 {
     // Include needed files
     require_once dirname(dirname(__DIR__)) . DS . 'tables' . DS . 'asset.association.php';
     require_once dirname(dirname(__DIR__)) . DS . 'tables' . DS . 'asset.php';
     require_once dirname(__DIR__) . DS . 'asset.php';
     // Get the file
     if (isset($_FILES['files'])) {
         $file = $_FILES['files']['name'][0];
         $size = (int) $_FILES['files']['size'];
         // Get the file extension
         $pathinfo = pathinfo($file);
         $filename = $pathinfo['filename'];
         $ext = $pathinfo['extension'];
     } else {
         return array('error' => 'No files provided');
     }
     // @FIXME: should these come from the global settings, or should they be courses specific
     // Get config
     $config = Component::params('com_media');
     // Max upload size
     $sizeLimit = (int) $config->get('upload_maxsize');
     $sizeLimit = $sizeLimit * 1024 * 1024;
     // Check to make sure we have a file and its not too big
     if ($size == 0) {
         return array('error' => 'File is empty');
     }
     if ($size > $sizeLimit) {
         $max = preg_replace('/<abbr \\w+=\\"\\w+\\">(\\w{1,3})<\\/abbr>/', '$1', \Hubzero\Utility\Number::formatBytes($sizeLimit));
         return array('error' => "File is too large. Max file upload size is {$max}");
     }
     // Create our asset table object
     $assetObj = new Tables\Asset($this->db);
     $this->asset['title'] = $filename;
     $this->asset['type'] = !empty($this->asset['type']) ? $this->asset['type'] : 'file';
     $this->asset['subtype'] = !empty($this->asset['subtype']) ? $this->asset['subtype'] : 'file';
     $this->asset['url'] = $file;
     $this->asset['created'] = Date::toSql();
     $this->asset['created_by'] = App::get('authn')['user_id'];
     $this->asset['course_id'] = Request::getInt('course_id', 0);
     // Save the asset
     if (!$assetObj->save($this->asset)) {
         return array('error' => 'Asset save failed');
     }
     // Create asset assoc object
     $assocObj = new Tables\AssetAssociation($this->db);
     $this->assoc['asset_id'] = $assetObj->get('id');
     $this->assoc['scope'] = Request::getCmd('scope', 'asset_group');
     $this->assoc['scope_id'] = Request::getInt('scope_id', 0);
     // Save the asset association
     if (!$assocObj->save($this->assoc)) {
         return array('error' => 'Asset association save failed');
     }
     // Get courses config
     $cconfig = Component::params('com_courses');
     // Build the upload path if it doesn't exist
     $uploadDirectory = PATH_APP . DS . trim($cconfig->get('uploadpath', '/site/courses'), DS) . DS . $this->asset['course_id'] . DS . $this->assoc['asset_id'] . DS;
     // Make sure upload directory exists and is writable
     if (!is_dir($uploadDirectory)) {
         if (!Filesystem::makeDirectory($uploadDirectory, 0755, true)) {
             return array('error' => 'Server error. Unable to create upload directory');
         }
     }
     if (!is_writable($uploadDirectory)) {
         return array('error' => 'Server error. Upload directory isn\'t writable');
     }
     // Get the final file path
     $target_path = $uploadDirectory . $filename . '.' . $ext;
     // Move the file to the site folder
     set_time_limit(60);
     // Scan for viruses
     if (!Filesystem::isSafe($_FILES['files']['tmp_name'][0])) {
         // Scan failed, delete asset and association and return an error
         $assetObj->delete();
         $assocObj->delete();
         Filesystem::deleteDirectory($uploadDirectory);
         return array('error' => 'File rejected because the anti-virus scan failed.');
     }
     if (!($move = move_uploaded_file($_FILES['files']['tmp_name'][0], $target_path))) {
         // Move failed, delete asset and association and return an error
         $assetObj->delete();
         $assocObj->delete();
         Filesystem::deleteDirectory($uploadDirectory);
         return array('error' => 'Move file failed');
     }
     // Get the url to return to the page
     $course_id = Request::getInt('course_id', 0);
     $offering_alias = Request::getCmd('offering', '');
     $course = new \Components\Courses\Models\Course($course_id);
     $url = Route::url('index.php?option=com_courses&controller=offering&gid=' . $course->get('alias') . '&offering=' . $offering_alias . '&asset=' . $assetObj->get('id'));
     $url = rtrim(str_replace('/api', '', Request::root()), '/') . '/' . ltrim($url, '/');
     $return_info = array('asset_id' => $this->assoc['asset_id'], 'asset_title' => $this->asset['title'], 'asset_type' => $this->asset['type'], 'asset_subtype' => $this->asset['subtype'], 'asset_url' => $url, 'course_id' => $this->asset['course_id'], 'offering_alias' => Request::getCmd('offering', ''), 'scope_id' => $this->assoc['scope_id'], 'asset_ext' => $ext, 'upload_path' => $uploadDirectory, 'target_path' => $target_path);
     // Return info
     return array('assets' => $return_info);
 }
Beispiel #2
0
 /**
  * Reorders assets
  *
  * @apiMethod POST
  * @apiUri    /courses/asset/reorder
  * @apiParameter {
  * 		"name":        "asset",
  * 		"description": "Array of IDs of assets to reorder",
  * 		"type":        "array",
  * 		"required":    true,
  * 		"default":     null
  * }
  * @apiParameter {
  * 		"name":        "scope",
  * 		"description": "Asset scope",
  * 		"type":        "string",
  * 		"required":    true,
  * 		"default":     null
  * }
  * @apiParameter {
  * 		"name":        "scope_id",
  * 		"description": "Asset scope ID",
  * 		"type":        "integer",
  * 		"required":    true,
  * 		"default":     null
  * }
  * @return    void
  */
 public function reorderTask()
 {
     // Get our asset group object
     $database = App::get('db');
     $assetAssocationObj = new AssetAssociation($database);
     $assets = Request::getVar('asset', array());
     $scope_id = Request::getInt('scope_id', 0);
     $scope = Request::getWord('scope', 'asset_group');
     $order = 1;
     foreach ($assets as $asset_id) {
         if (!$assetAssocationObj->loadByAssetScope($asset_id, $scope_id, $scope)) {
             App::abort(500, "Loading asset association {$asset_id} failed");
         }
         // Save the asset group
         if (!$assetAssocationObj->save(array('ordering' => $order))) {
             App::abort(500, 'Asset asssociation save failed');
         }
         $order++;
     }
     // Return message
     $this->send('New asset order saved');
 }
Beispiel #3
0
 /**
  * Copy an entry and associated data
  *
  * @param   integer $offering_id New offering to copy to
  * @param   boolean $deep        Copy associated data?
  * @return  boolean True on success, false on error
  */
 public function copy($offering_id = null, $deep = true)
 {
     // Get some old info we may need
     //  - Unit ID
     //  - Offering ID
     $u_id = $this->get('id');
     $o_id = $this->get('offering_id');
     // Reset the ID. This will force store() to create a new record.
     $this->set('id', 0);
     // Are we copying to a new offering?
     if ($offering_id) {
         $this->set('offering_id', $offering_id);
     } else {
         // Copying to the same offering so we want to distinguish
         // this unit from the one we copied from
         $this->set('title', $this->get('title') . ' (copy)');
         $this->set('alias', $this->get('alias') . '_copy');
     }
     if (!$this->store()) {
         return false;
     }
     if ($deep) {
         // Copy assets
         $tbl = new Tables\AssetAssociation($this->_db);
         //foreach ($this->assets(array('asset_scope_id' => $u_id)) as $asset)
         foreach ($tbl->find(array('scope_id' => $u_id, 'scope' => 'unit')) as $asset) {
             $tbl->bind($asset);
             $tbl->id = 0;
             $tbl->scope_id = $this->get('id');
             //if (!$asset->copy($this->get('id')))
             if (!$tbl->store()) {
                 $this->setError($tbl->getError());
             }
         }
         // Copy asset groups
         foreach ($this->assetgroups(null, array('unit_id' => $u_id, 'parent' => 0)) as $assetgroup) {
             if (!$assetgroup->copy($this->get('id'), $deep)) {
                 $this->setError($assetgroup->getError());
             }
         }
     }
     return true;
 }
Beispiel #4
0
 /**
  * Cancel a course page task
  *
  * @return  void
  */
 public function reorderTask()
 {
     // Check for request forgeries
     Request::checkToken();
     $move = $this->_task == 'orderup' ? -1 : 1;
     // Incoming
     $id = Request::getVar('id', array());
     $id = $id[0];
     $tmpl = Request::getVar('tmpl', '');
     $scope = Request::getVar('scope', 'asset_group');
     $scope_id = Request::getInt('scope_id', 0);
     $course_id = Request::getInt('course_id', 0);
     // Get the element moving down - item 1
     $tbl = new Tables\AssetAssociation($this->database);
     $tbl->loadByAssetScope($id, $scope_id, $scope);
     if (!$tbl->move($move, "scope=" . $this->database->Quote($scope) . " AND scope_id=" . $this->database->Quote(intval($scope_id)))) {
         echo $tbl->getError();
         return;
     }
     App::redirect(Route::url('index.php?option=' . $this->_option . '&controller=' . $this->_controller . '&tmpl=' . $tmpl . '&scope=' . $scope . '&scope_id=' . $scope_id . '&course_id=' . $course_id, false));
 }
Beispiel #5
0
 /**
  * Copy an entry and associated data
  *
  * @param   integer $course_id New course to copy to
  * @param   boolean $deep      Copy associated data?
  * @return  boolean True on success, false on error
  */
 public function copy($course_id = null, $deep = true)
 {
     // Get some old info we may need
     //  - Offering ID
     //  - Course ID
     $o_id = $this->get('id');
     $c_id = $this->get('course_id');
     $oldOfferingAssets = $this->assets();
     // Reset the ID. This will force store() to create a new record.
     $this->set('id', 0);
     // Are we copying to a new course?
     if ($course_id) {
         $this->set('course_id', $course_id);
     } else {
         // Copying to the same course so we want to distinguish
         // this offering from the one we copied from
         $this->set('title', $this->get('title') . ' (copy)');
         $this->set('alias', $this->get('alias') . '_copy');
     }
     if (!$this->store()) {
         return false;
     }
     if ($deep) {
         // Copy pages
         foreach ($this->pages(array('offering_id' => $o_id, 'active' => array(0, 1)), true) as $page) {
             if (!$page->copy($this->get('course_id'), $this->get('id'))) {
                 $this->setError($page->getError());
             }
         }
         // Copy units
         foreach ($this->units(array('offering_id' => $o_id, 'section_id' => -1), true) as $unit) {
             if (!$unit->copy($this->get('id'))) {
                 $this->setError($unit->getError());
             }
         }
         // Copy logo
         if ($file = $this->logo('file')) {
             $src = DS . trim($this->config('uploadpath', '/site/courses'), '/') . DS . $c_id . '/offerings/' . $o_id . DS . $file;
             if (file_exists(PATH_APP . $src)) {
                 $dest = DS . trim($this->config('uploadpath', '/site/courses'), '/') . DS . $this->get('course_id') . '/offerings/' . $this->get('id');
                 if (!is_dir(PATH_APP . $dest)) {
                     if (!Filesystem::makeDirectory(PATH_APP . $dest)) {
                         $this->setError(Lang::txt('UNABLE_TO_CREATE_UPLOAD_PATH'));
                     }
                 }
                 $dest .= DS . $file;
                 if (!Filesystem::copy(PATH_APP . $src, PATH_APP . $dest)) {
                     $this->setError(Lang::txt('Failed to copy offering logo.'));
                 }
             }
         }
         // Copy assets (grab the assets from the original offering)
         if ($oldOfferingAssets) {
             foreach ($oldOfferingAssets as $asset) {
                 $oldAssetId = $asset->get('id');
                 if (!$asset->copy()) {
                     $this->setError($asset->getError());
                 } else {
                     // Copy asset associations
                     $tbl = new Tables\AssetAssociation($this->_db);
                     foreach ($tbl->find(array('scope_id' => $o_id, 'scope' => 'offering', 'asset_id' => $oldAssetId)) as $aa) {
                         $tbl->bind($aa);
                         $tbl->id = 0;
                         $tbl->scope_id = $this->get('id');
                         $tbl->asset_id = $asset->get('id');
                         if (!$tbl->store()) {
                             $this->setError($tbl->getError());
                         }
                     }
                 }
             }
         }
     }
     return true;
 }
Beispiel #6
0
 /**
  * Get a count or list of parents for this entry
  *
  * @param   array $filters Fitlers to apply to results query
  * @return  array
  */
 public function parents($filters = array())
 {
     if (!isset($filters['asset_id'])) {
         $filters['asset_id'] = (int) $this->get('id');
     }
     $tbl = new Tables\AssetAssociation($this->_db);
     if (isset($filters['count']) && $filters['count']) {
         return $tbl->count($filters);
     }
     if (!($results = $tbl->find($filters))) {
         $results = array();
     }
     return $results;
 }
Beispiel #7
0
 /**
  * Create method for this handler
  *
  * @return array of assets created
  **/
 public function create()
 {
     // Include needed files
     require_once dirname(dirname(__DIR__)) . DS . 'tables' . DS . 'asset.association.php';
     require_once dirname(dirname(__DIR__)) . DS . 'tables' . DS . 'asset.php';
     require_once dirname(__DIR__) . DS . 'asset.php';
     // Get the file
     if (isset($_FILES['files'])) {
         $file = $_FILES['files']['name'][0];
         $size = (int) $_FILES['files']['size'];
         // Get the file extension
         $pathinfo = pathinfo($file);
         $filename = $pathinfo['filename'];
         $ext = $pathinfo['extension'];
     } else {
         return array('error' => 'No files provided');
     }
     // @FIXME: should these come from the global settings, or should they be courses specific
     // Get config
     $config = Component::params('com_media');
     // Max upload size
     $sizeLimit = (int) $config->get('upload_maxsize');
     $sizeLimit = $sizeLimit * 1024 * 1024;
     // Check to make sure we have a file and its not too big
     if ($size == 0) {
         return array('error' => 'File is empty');
     }
     if ($size > $sizeLimit) {
         $max = preg_replace('/<abbr \\w+=\\"\\w+\\">(\\w{1,3})<\\/abbr>/', '$1', \Hubzero\Utility\Number::formatBytes($sizeLimit));
         return array('error' => "File is too large. Max file upload size is {$max}");
     }
     // get request vars
     $course_id = Request::getInt('course_id', 0);
     $offering_alias = Request::getCmd('offering', '');
     $scope = Request::getCmd('scope', 'asset_group');
     $scope_id = Request::getInt('scope_id', 0);
     // get all assets in group
     $assetGroup = new \Components\Courses\Models\Assetgroup($scope_id);
     $assets = $assetGroup->assets();
     // check to see if any of our assets are html5?
     $hubpresenter = null;
     foreach ($assets as $asset) {
         if ($asset->get('type') == 'video' && $asset->get('subtype') == 'video' && in_array($asset->get('state'), array(0, 1)) && strpos($asset->get('url'), 'zip')) {
             $hubpresenter = $asset;
             break;
         }
     }
     // make sure we have asset
     if ($hubpresenter === null) {
         return array('error' => 'Unable to locate html5 video or hubpresenter asset to attach subtitle file to.');
     }
     // build path to asset
     $pathToAsset = $hubpresenter->path($course_id);
     $pathToAssetFolder = trim(dirname($pathToAsset), DS);
     // build target path
     $target_path = PATH_APP . DS . $pathToAssetFolder . DS . $filename . '.' . $ext;
     // Move the file to the site folder
     set_time_limit(60);
     // Scan for viruses
     if (!Filesystem::isSafe($_FILES['files']['tmp_name'][0])) {
         // Scan failed, return an error
         return array('error' => 'File rejected because the anti-virus scan failed.');
     }
     // move file
     if (!($move = move_uploaded_file($_FILES['files']['tmp_name'][0], $target_path))) {
         // Move failed, delete asset and association and return an error
         return array('error' => 'Move file failed');
     }
     // get json file
     $jsonFile = $pathToAssetFolder . DS . 'presentation.json';
     // get manifest
     $manifest = file_get_contents(PATH_APP . DS . $jsonFile);
     $manifest = json_decode($manifest);
     // make sure we have a subtitles section
     $currentSubtitles = array();
     if (!isset($manifest->presentation->subtitles)) {
         $manifest->presentation->subtitles = array();
     } else {
         foreach ($manifest->presentation->subtitles as $subtitle) {
             $currentSubtitles[] = $subtitle->source;
         }
     }
     // create subtitle details based on filename
     $info = pathinfo($file);
     $name = str_replace('-auto', '', $info['filename']);
     $autoplay = strstr($info['filename'], '-auto') ? 1 : 0;
     $source = $file;
     // use only the last segment from name (ex. ThisIsATest.English => English)
     $nameParts = explode('.', $name);
     $name = array_pop($nameParts);
     // add subtitle
     $subtitle = new stdClass();
     $subtitle->type = 'SRT';
     $subtitle->name = ucfirst($name);
     $subtitle->source = $source;
     $subtitle->autoplay = $autoplay;
     // only add sub if we dont already have it
     if (!in_array($subtitle->source, $currentSubtitles)) {
         $manifest->presentation->subtitles[] = $subtitle;
     }
     // update json file
     file_put_contents(PATH_APP . DS . $jsonFile, json_encode($manifest, JSON_PRETTY_PRINT));
     //parse subtitle file
     $lines = self::_parseSubtitleFile($target_path);
     // make transcript file
     $transcript = '';
     foreach ($lines as $line) {
         $transcript .= ' ' . trim($line->text);
     }
     // trim transcript and replace add slide markers
     $transcript = str_replace(array("\r\n", "\n"), array('', ''), $transcript);
     $transcript = preg_replace("/\\[([^\\]]*)\\]/ux", "\n\n[\$1]", $transcript);
     // add title to transcript
     $transcript = $manifest->presentation->title . PHP_EOL . str_repeat('==', 20) . PHP_EOL . ltrim($transcript, PHP_EOL);
     // Create our asset table object
     $assetObj = new Tables\Asset($this->db);
     $this->asset['title'] = 'Video Transcript';
     $this->asset['type'] = 'file';
     $this->asset['subtype'] = 'file';
     $this->asset['url'] = $info['filename'] . '.txt';
     $this->asset['created'] = Date::toSql();
     $this->asset['created_by'] = App::get('authn')['user_id'];
     $this->asset['course_id'] = $course_id;
     // Save the asset
     if (!$assetObj->save($this->asset)) {
         return array('error' => 'Asset save failed');
     }
     // Create asset assoc object
     $assocObj = new Tables\AssetAssociation($this->db);
     $this->assoc['asset_id'] = $assetObj->get('id');
     $this->assoc['scope'] = $scope;
     $this->assoc['scope_id'] = $scope_id;
     // Save the asset association
     if (!$assocObj->save($this->assoc)) {
         return array('error' => 'Asset association save failed');
     }
     // Get courses config
     $cconfig = Component::params('com_courses');
     // Build the upload path if it doesn't exist
     $uploadDirectory = PATH_APP . DS . trim($cconfig->get('uploadpath', '/site/courses'), DS) . DS . $this->asset['course_id'] . DS . $this->assoc['asset_id'] . DS;
     // Make sure upload directory exists and is writable
     if (!is_dir($uploadDirectory)) {
         if (!Filesystem::makeDirectory($uploadDirectory)) {
             return array('error' => 'Server error. Unable to create upload directory');
         }
     }
     if (!is_writable($uploadDirectory)) {
         return array('error' => 'Server error. Upload directory isn\'t writable');
     }
     // Get the final file path
     $transcript_target_path = $uploadDirectory . $this->asset['url'];
     // make transcript file
     file_put_contents($transcript_target_path, $transcript);
     // Get the url to return to the page
     $course_id = Request::getInt('course_id', 0);
     $offering_alias = Request::getCmd('offering', '');
     $course = new \Components\Courses\Models\Course($course_id);
     $url = Route::url('index.php?option=com_courses&controller=offering&gid=' . $course->get('alias') . '&offering=' . $offering_alias . '&asset=' . $assetObj->get('id'));
     // build return info
     $return_info = array('asset_id' => $this->assoc['asset_id'], 'asset_title' => $this->asset['title'], 'asset_type' => $this->asset['type'], 'asset_subtype' => $this->asset['subtype'], 'asset_url' => $url, 'course_id' => $this->asset['course_id'], 'offering_alias' => Request::getCmd('offering', ''), 'scope_id' => $this->assoc['scope_id'], 'asset_ext' => 'txt', 'upload_path' => $uploadDirectory, 'target_path' => $transcript_target_path);
     // Return info
     return array('assets' => $return_info);
 }
Beispiel #8
0
 /**
  * Save method for this handler
  * // @FIXME: reduce code duplication here
  *
  * @return array of assets created
  **/
 public function save()
 {
     // Include needed files
     require_once PATH_CORE . DS . 'components' . DS . 'com_courses' . DS . 'models' . DS . 'asset.php';
     // Create our asset object
     $id = Request::getInt('id', null);
     $asset = new \Components\Courses\Models\Asset($id);
     // Grab the incoming content
     $content = Request::getVar('content', '', 'default', 'none', 2);
     // Get everything ready to store
     // Check if vars are already set (i.e. by a sub class), before setting them here
     $asset->set('title', !empty($this->asset['title']) ? $this->asset['title'] : strip_tags(substr($content, 0, 25)));
     $asset->set('type', !empty($this->asset['type']) ? $this->asset['type'] : 'text');
     $asset->set('subtype', !empty($this->asset['subtype']) ? $this->asset['subtype'] : 'content');
     $asset->set('content', !empty($this->asset['content']) ? $this->asset['content'] : $content);
     // If we have a state coming in as an int
     if ($graded = Request::getInt('graded', false)) {
         $asset->set('graded', $graded);
         // By default, weight asset as a 'homework' type
         $grade_weight = $asset->get('grade_weight');
         if (empty($grade_weight)) {
             $asset->set('grade_weight', 'homework');
         } else {
             $asset->set('grade_weight', $grade_weight);
         }
     } elseif ($graded = Request::getInt('edit_graded', false)) {
         $asset->set('graded', 0);
     }
     // If we're saving progress calculation var
     if ($progress = Request::getInt('progress_factors', false)) {
         $asset->set('progress_factors', array('asset_id' => $asset->get('id'), 'section_id' => Request::getInt('section_id', 0)));
     } elseif (Request::getInt('edit_progress_factors', false)) {
         $asset->set('section_id', Request::getInt('section_id', 0));
         $asset->set('progress_factors', 'delete');
     }
     // Save the asset
     if (!$asset->store()) {
         return array('error' => 'Asset save failed');
     }
     $scope_id = Request::getInt('scope_id', null);
     $original_scope_id = Request::getInt('original_scope_id', null);
     $scope = Request::getCmd('scope', 'asset_group');
     // Only worry about this if scope id is changing
     if (!is_null($scope_id) && !is_null($original_scope_id) && $scope_id != $original_scope_id) {
         // Create asset assoc object
         require_once PATH_CORE . DS . 'components' . DS . 'com_courses' . DS . 'tables' . DS . 'asset.association.php';
         $assoc = new Tables\AssetAssociation($this->db);
         if (!$assoc->loadByAssetScope($asset->get('id'), $original_scope_id, $scope)) {
             return array('error' => 'Failed to load asset association');
         }
         // Save the asset association
         if (!$assoc->save(array('scope_id' => $scope_id))) {
             return array('error' => 'Asset association save failed');
         }
     }
     // Get the url to return to the page
     $course_id = Request::getInt('course_id', 0);
     $offering_alias = Request::getCmd('offering', '');
     $course = new \Components\Courses\Models\Course($course_id);
     $course->offering($offering_alias);
     $url = Route::url($course->offering()->link() . '&asset=' . $asset->get('id'));
     $url = rtrim(str_replace('/api', '', Request::root()), '/') . '/' . ltrim($url, '/');
     $files = array('asset_id' => $asset->get('id'), 'asset_title' => $asset->get('title'), 'asset_type' => $asset->get('type'), 'asset_subtype' => $asset->get('subtype'), 'asset_url' => $url, 'asset_state' => $asset->get('state'), 'scope_id' => $scope_id);
     $return_info = array('asset_id' => $asset->get('id'), 'asset_title' => $asset->get('title'), 'asset_type' => $asset->get('type'), 'asset_subtype' => $asset->get('subtype'), 'asset_url' => $url, 'course_id' => $asset->get('course_id'), 'offering_alias' => $offering_alias, 'scope_id' => $scope_id, 'files' => array($files));
     // Return info
     return array('assets' => $return_info);
 }