* * @todo * implement the help of the video upload (Implement the internal hook for the help video_upload_v_help()). */ /** * Implementation of hook_menu */ function video_upload_menu() { $items = array(); $items['node/add/video/upload'] = array( 'title' => 'Upload', 'access arguments' => array('create video') ); $items['admin/settings/video/upload'] = array( 'title' => 'Upload', 'description' => 'Configure various settings of the video upload plugin.', 'access arguments' => array('administer site configuration'), 'page callback' => 'drupal_get_form', 'page arguments' => array('video_upload_admin_settings'), 'type' => MENU_NORMAL_ITEM, ); return $items; } /** * Setting form for video_upload */ function video_upload_admin_settings() { $form = array(); $form['video_upload_allowed_extensions'] = array( '#type' => 'textfield', '#title' => t('Allowed extensions'), '#description' => t('A comma separated list of video extesions uploadable with the video upload feature. Do not insert any space.'), '#default_value' => variable_get('video_upload_allowed_extensions', 'mov,flv,wmv'), ); $form['video_upload_path_prefix'] = array( '#type' => 'textfield', '#title' => t('Pattern for the file prefix'), '#description' => t('Specify the pattern to prefix to file names uploaded with the video_upload module. It will be appended after the site files directory (e.g., files) but before the file name itself. Do not include a leading or trailing slash. Spaces will be converted to underscores to avoid file system issues.'), '#default_value' => variable_get('video_upload_path_prefix', 'videos'), ); $form['token_help'] = array( '#title' => t('Replacement patterns'), '#type' => 'fieldset', '#collapsible' => TRUE, '#collapsed' => TRUE, '#description' => t('Prefer raw-text replacements for text to avoid problems with HTML entities!'), ); $form['token_help']['help'] = array( '#value' => theme('token_help', 'node'), ); return system_settings_form($form); } /** * Implementation of hook_cron(). * Look for uploaded videos which have not been submitted (only previews) and * delete them */ function video_upload_cron() { /* look for crusty files */ $temppath = file_directory_temp() . '/video/'; $files = file_scan_directory(file_create_path($temppath), '.*'); foreach ($files as $file => $info) { if (time() - filemtime($file) > 60*60*6) { db_query("DELETE FROM {files} WHERE filename LIKE 'video_upload_temp.%' AND nid = 1 AND filepath = '%s'", $file); file_delete($file); } } } /** * Implementation of hook_v_help */ function video_upload_v_help() { $help = array(); $help['upload']['data'] = '' . t('Upload support') . ''; $help['upload']['children'] = array(t('You can upload a video file from your computer to this website.')); return $help; } /** * Implementation of hook_v_info() */ function video_upload_v_info() { $info['upload'] = array( '#name' => 'Upload Video', '#description' => t('Post a video available on your computer as a file to this website.'), '#downloadable' => true, '#autothumbable' => module_exists('video_ffmpeg_helper') && variable_get('video_image_auto_thumbnail', false), '#autoresolution' => module_exists('video_ffmpeg_helper') && variable_get('video_ffmpeg_helper_auto_resolution', false), '#autoplaytime' => module_exists('video_ffmpeg_helper') && variable_get('video_ffmpeg_helper_auto_playtime', false), ); return $info; } /** * Implements the hook_v_auto_thumnail */ function video_upload_v_auto_thumbnail(&$node) { // as we rely on ffmpeg_helper, let's check if we have video_ffmpeg_helper_installed if(module_exists('video_ffmpeg_helper')) { return _video_ffmpeg_helper_auto_thumbnail($node); } return false; } /** * Implements the hook_v_auto_resolution */ function video_upload_v_auto_resolution(&$node) { // as we rely on ffmpeg_helper, let's check if we have video_ffmpeg_helper_installed if(module_exists('video_ffmpeg_helper')) { return _video_ffmpeg_helper_auto_resolution($node); } return false; } /** * Implements the hook_v_auto_resolution */ function video_upload_v_auto_playtime(&$node) { // as we rely on ffmpeg_helper, let's check if we have video_ffmpeg_helper_installed if(module_exists('video_ffmpeg_helper')) { return _video_ffmpeg_helper_auto_playtime($node); } return false; } /** * Implements the hook_v_download */ function video_upload_v_download($node) { // the code below comes from the audio.module // The mime_header_encode function does not (yet) support // quoted-string encoding of ASCII strings with special // characters. See discussion at http://drupal.org/node/82614 $filename = basename($node->current_video_upload_file->filename); // If the string contains non-ASCII characters, process it through // the mime_header_encode function. if (preg_match('/[^\x20-\x7E]/', $filename)) { $filename = mime_header_encode($filename); } // Otherwise, if the string contains special characters (like // space), perform quoted-string encoding. elseif (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $filename)) { $filename = '"'. str_replace('"', '\"', $filename) .'"'; } $headers = array( 'Content-Type: '. mime_header_encode($node->current_video_upload_file->filemime), 'Content-Length: '. $node->current_video_upload_file->filesize, 'Content-Disposition: attachment; filename='. $filename, ); video_upload_file_transfer($node->current_video_upload_file->filepath, $headers); } /** * Variation on Drupal's file_transfer() function. The only difference * is that set_time_limit() is called to allow for large files. * This code comes from audio module * * @param $source File to transfer. * @param $headers An array of http headers to send along with file. */ function video_upload_file_transfer($source, $headers) { ob_end_clean(); foreach ($headers as $header) { // To prevent HTTP header injection, we delete new lines that are // not followed by a space or a tab. // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 $header = preg_replace('/\r?\n(?!\t| )/', '', $header); header($header); } $source = file_create_path($source); // Transfer file in 1024 byte chunks to save memory usage. if ($fd = fopen($source, 'rb')) { if (!ini_get('safe_mode')){ set_time_limit(0); } while (!feof($fd)) { print fread($fd, 1024); ob_flush(); flush(); } fclose($fd); } else { drupal_not_found(); } exit(); } /** * Implementation of hook_v_form() */ function video_upload_v_form(&$node, &$form) { //print 'form'; // add js stuff for the 'upload in progess' message theme('video_upload_get_script'); // add hidden html used for the 'upload in progess' message $form['#suffix'] = theme('video_upload_busy'); // required for upload to work $form['#attributes']['enctype'] = 'multipart/form-data'; $form['video'] += _video_upload_form($node); return $form; } /** * Implementation of hook_nodeapi() */ function video_upload_nodeapi(&$node, $op, $teaser, $page) { if($node->type == 'video' && $node->vtype == 'upload') { switch ($op) { case 'load': //exit; //print_r($node); //exit; return _video_upload_load($node); break; case 'prepare': //exit; _video_upload_prepare($node); break; case 'validate': //exit; //_video_upload_validate($node); break; case 'presave': //exit; _video_upload_presave($node); break; case 'insert': _video_upload_insert($node); ////_video_upload_validate($node); break; case 'update': // exit; _video_upload_update($node); break; case 'delete': //exit; _video_upload_delete($node); break; case 'delete revision': //exit; video_upload_delete_revision($node); break; case 'view': // exit; _video_upload_view($node); } } } function _video_upload_load(&$node) { $fileBuf = db_fetch_object(db_query('SELECT fid FROM {video_upload} WHERE nid = %d', $node->nid)); $output = array(); $output['video_fid'] = $fileBuf->fid; $file = _video_upload_get_file($output['video_fid']); $output['current_video_upload_file'] = $file; $output['vidfile'] = file_create_url($file->filepath); // set the filesize $output['size'] = $file->filesize; //print_r($output); return $output; } /* The following hooks implementation is pretty Drupal voodoo :-) .. you should be pretty confortable on drupal apis. See http://www.varesano.net/blog/fabio/understanding+drupal+hook+nodeapi+execution+order for some hints */ function _video_upload_prepare(&$node) { if (!count($_POST)) return; } /** * Create video upload specific form fields */ function _video_upload_form(&$node) { _video_upload_check_settings(); $form = array(); if($node->new_video_upload_file) { // there is a newly uploaded file (this has been initialized by _prepare()) $form['new_video_upload_file_fid'] = array('#type' => 'hidden', '#value' => $node->new_video_upload_file->fid); $form['new_video_upload_file_info'] = array('#type' => 'item', '#value' => theme('video_upload_file_info_form', $node->new_video_upload_file, $node), '#weight' => -10); $we_have_video = true; } else { //$form['new_video_upload_file_fid'] = array('#type' => 'hidden', '#value' => 0); if($node->current_video_upload_file) { // we don't have a new file $form['current_video_upload_file_fid'] = array('#type' => 'hidden', '#value' => $node->current_video_upload_file->fid); $form['current_video_upload_file_info'] = array('#type' => 'item', '#value' => theme('video_upload_file_info_form', $node->current_video_upload_file, $node), '#weight' => -10); $we_have_video = true; } } $form['new_video_upload_file_fid'] = array('#type' => 'hidden', '#value' => 0); $form['video_upload_file'] = array( '#type' => 'file', '#title' => $we_have_video ? t('Replace with') : t('Upload video file'), '#size' => 40, '#weight' => -9, '#description' => t('Choose a video file from your pc.
NOTE: The max upload size is') . ' ' . format_size(file_upload_max_size()) . '.', // no need to set this as required as we do validation in the validate nodeapi hook ); return $form; } /** * Validate video file */ function video_upload_v_validate(&$node) { // in Drupal 6 version all file size and the type validations are done by the file API's } function _video_upload_presave(&$node) { //print 'submit'; //print_r($node); die; // ####### Prepare by moving file to the temp location and then checking the validations of fields if (is_object($node->video_upload_file)) { $file_field = $node->video_upload_file; } else { $file_field = 'video_upload_file'; } // get extention array $extentions = explode(",",variable_get('video_upload_allowed_extensions', 'mov,flv,wmv')); $validators = array( 'file_validate_extensions' => array( 'csv' ), ); // TODO : add file size validation // 'file_validate_size' => array($limits['file_size'], $limits['user_size']), if (count($_POST) && $file = file_save_upload($file_field , array('file_validate_extensions' => array('mov flv wmv')))) { // a file has been uploaded $node->new_video_upload_file = $file; $node->new_video_upload_file_fid = $file->fid; //print_r($file); //exit; } else if (($node->new_video_upload_file_fid || $_POST['new_video_upload_file_fid']) && $_POST['op'] == 'Submit') { $node->new_video_upload_file = _video_upload_get_file($_POST['new_video_upload_file_fid']); } else if (($node->new_video_upload_file_fid || $_POST['new_video_upload_file_fid']) && $_POST['op'] == 'Preview') { $node->new_video_upload_file = _video_upload_get_file($_POST['new_video_upload_file_fid']); } //$node->new_video_upload_file_fid = $file->fid; // // ####### Start Perpare to save ############### if($node->new_video_upload_file_fid) { $fid = $node->new_video_upload_file_fid; } else { $fid = $node->current_video_upload_file_fid; } $node->serial_data['video_fid'] = $fid; $node->vidfile = $node->new_video_upload_file->path; $node->size = $node->new_video_upload_file->filesize; // _video_upload_insert($file,$node); } function _video_upload_insert(&$node) { //print "insert"; //print_r($node); //exit; if($node->new_video_upload_file_fid && $file = _video_upload_get_file($node->new_video_upload_file_fid)) { // there is a new file uploaded (now stored on the temp path); need to store in the final directory _video_upload_store_file($file, $node); } } function _video_upload_update(&$node) { if($node->new_video_upload_file_fid && $file = _video_upload_get_file($node->new_video_upload_file_fid)) { // there is a new file uploaded (now stored on the temp path) //need to store in the final directory //exit; if($node->current_video_upload_file_fid) { // let's delete the old video _video_upload_delete_file($node->current_video_upload_file_fid); } _video_upload_store_file($file, $node); } } /** * Delete files associated to this video node */ function _video_upload_delete(&$node) { //print 'delete'; // delete file file_delete($node->current_video_upload_file->path); // delete file information from database db_query('DELETE FROM {upload} WHERE fid = %d', $node->current_video_upload_file->fid); db_query('DELETE FROM {files} WHERE fid = %d', $node->current_video_upload_file->fid); } /** * */ function _video_upload_view(&$node) { //print 'view'; } /** * Move a temp file into the final directory associating it with the node */ function _video_upload_store_file(&$file, &$node) { $file->filename = _video_get_original_filename($file->filename); _video_upload_get_path($file, $node); if (file_move($file, file_directory_path())) { // file moved successfully if(variable_get('video_ffmpeg_helper_auto_conversion', false)) $status = 0; // ffmpeg will use this as source, so let drupal delete the file later else $status = 1; // ffmpeg will not be called, this video file will play as-is // update the file db entry db_query("UPDATE {files} SET filename = '%s', filepath = '%s', filemime = '%s', filesize = %d, status = %d WHERE fid = %d", $file->filename, $file->filepath, $file->filemime, $file->filesize, $status, $file->fid); // add an entry in the file_revisions table db_query("INSERT INTO {video_upload} (vid, nid, fid) VALUES (%d, %d, %d)", $node->vid, $node->nid, $file->fid); // update the file db entry //db_query("UPDATE {video} SET serialized_data = '%s' WHERE vid = %d", $file->filename, $file->filepath, $file->filemime, $file->filesize, $file->fid); } else { drupal_set_message(t('An error occurred during file saving. Your video file has not been stored.'), 'error'); $rep = array( '!path' => $file, '!dest' => $dest_path, ); watchdog('video_upload', 'moving file !path to !dest failed', $rep); } } /** * Gets the definitive path for stored videos */ function _video_upload_get_path(&$file, &$node) { // this code is from uploadpath.module $file_name = str_replace(array(' ', "\n", "\t"), '_', token_replace(variable_get('video_upload_path_prefix', 'videos') . '/', 'node', $node)) . $file->filename; // Create the directory if it doesn't exist yet. $dirs = explode('/', dirname($file_name)); $directory = file_directory_path(); while (count($dirs)) { $directory .= '/' . array_shift($dirs); file_check_directory($directory, FILE_CREATE_DIRECTORY); } $file->filename = $file_name; } /** * Get the file object with the given $fid. This function cache its results */ function _video_upload_get_file($fid) { static $files = array(); if (!$fid) { return null; } if (!isset($files[$fid])) { $files[$fid] = db_fetch_object(db_query('SELECT * from {files} WHERE fid = %d', $fid)); } return $files[$fid]; } /** * Delete a file */ function _video_upload_delete_file($file) { // delete file file_delete($file->path); // delete file information from database db_query('DELETE FROM {video_upload} WHERE fid = %d', $file); db_query('DELETE FROM {files} WHERE fid = %d', $file); } /** * Display informations about already uploaded file */ function theme_video_upload_file_info_form($file, $node) { // create array containing uploaded file informations $items = array( ''. t('file name') .': ' . _video_get_original_filename(basename($file->filename)), // do not display parent folders ''. t('file size') .': ' . format_size($file->filesize), ); // create information list $output .= theme_item_list($items, t('uploaded video information:')); return $output; } /** * Return the original filename (without 'video_upload_temp.') */ function _video_get_original_filename($filename) { if(strpos($filename, 'video_upload_temp.') === 0) { return substr($filename, strlen('video_upload_temp.')); } return $filename; } /** * Verify the video_upload module settings. */ function _video_upload_check_settings() { /* // File paths $video_path = file_create_path(variable_get('video_upload_default_path', 'videos')); $temp_path = rtrim($video_path, '/') . '/temp'; if (!file_check_directory($video_path, FILE_CREATE_DIRECTORY, 'video_upload_default_path')) { return false; } if (!file_check_directory($temp_path, FILE_CREATE_DIRECTORY, 'video_upload_default_path')) { return false; } */ return true; } /** * Import the video_upload.js script */ function theme_video_upload_get_script() { drupal_add_js(drupal_get_path('module', 'video_upload') . '/video_upload.js'); } /** * Renders a 'upload in progress' message */ function theme_video_upload_busy() { return ''; } /** * Implementation of hook_v_play */ function video_upload_v_play($node) { module_load_include('inc', 'video', '/includes/common'); return _video_common_get_player($node); } /** * Function to other modules to use to create image nodes. * * @param $filepath * String filepath of an image file. Note that this file will be moved into * the image module's images directory. * @param $title * String to be used as the node's title. If this is ommitted the filename * will be used. * @param $body * String to be used as the node's body. * @param $taxonomy * Taxonomy terms to assign to the node if the taxonomy.module is installed. * @return * A node object if the node is created successfully or FALSE on error. */ function video_upload_create_node_from($filepath, $title = NULL, $body = '', $taxonomy = NULL) { global $user; if (!user_access('create video')) { drupal_access_denied(); } if (!is_object($filepath)) { $p = $filepath; $filepath = new stdClass(); $filepath->filepath = $p; $filepath->filename = basename($p); $filepath->filesize = filesize($p); } // Ensure it's a valid video //if (!$image_info = image_get_info($filepath)) { // return FALSE; //} // Build the node. $node = new stdClass(); $node->type = 'video'; $node->vtype = 'upload'; $node->uid = $user->uid; $node->name = $user->name; $node->title = isset($title) ? $title : basename($filepath); $node->body = $body; // Set the node's defaults... (copied this from node and comment.module) $node_options = variable_get('node_options_'. $node->type, array('status', 'promote')); $node->status = in_array('status', $node_options); $node->promote = in_array('promote', $node_options); if (module_exists('comment')) { $node->comment = variable_get("comment_$node->type", COMMENT_NODE_READ_WRITE); } if (module_exists('taxonomy')) { $node->taxonomy = $taxonomy; } $node->video_upload_file = $filepath; node_invoke_nodeapi($node, 'prepare'); $node->new_video_upload_file_fid = $node->new_video_upload_file->fid; // Save the node. $node = node_submit($node); node_save($node); // Remove the original image now that the import has completed. file_delete($original_path); return $node; } /** * Implementation of hook_theme(). */ function video_upload_theme() { return array( 'video_upload_busy' => array( 'arguments' => array(), ), 'video_upload_file_info_form' => array( 'arguments' => array('file' => NULL,'node' => NULL), ), 'video_upload_get_script' => array( 'arguments' => array(), ), 'video_play_dcr' => array( 'arguments' => array('node' => NULL), ), 'video_play_divx' => array( 'arguments' => array('node' => NULL), ), 'video_play_flash' => array( 'arguments' => array('node' => NULL), ), 'video_play_ogg_theora' => array( 'arguments' => array('node' => NULL), ), 'video_play_quicktime' => array( 'arguments' => array('node' => NULL), ), 'video_play_realmedia' => array( 'arguments' => array('node' => NULL), ), 'video_play_swf' => array( 'arguments' => array('node' => NULL), ), 'video_play_windowsmedia' => array( 'arguments' => array('node' => NULL), ), ); }