diff options
Diffstat (limited to 'plugins/video_image')
-rw-r--r-- | plugins/video_image/video_image.info | 5 | ||||
-rw-r--r-- | plugins/video_image/video_image.module | 530 |
2 files changed, 424 insertions, 111 deletions
diff --git a/plugins/video_image/video_image.info b/plugins/video_image/video_image.info index 40677b2..8840ccd 100644 --- a/plugins/video_image/video_image.info +++ b/plugins/video_image/video_image.info @@ -1,5 +1,6 @@ -; $Id$ name = Video Image description = Enable thumbnails support for video module. -dependencies = image video +dependencies[] = image +dependencies[] = video package = "Video" +core = 6.x
\ No newline at end of file diff --git a/plugins/video_image/video_image.module b/plugins/video_image/video_image.module index 992795a..705ceba 100644 --- a/plugins/video_image/video_image.module +++ b/plugins/video_image/video_image.module @@ -1,37 +1,39 @@ <?php -// $Id$ /** * @file * Enable image support for video module. * * @author Fabio Varesano <fvaresano at yahoo dot it> + * porting to Drupal 6 + * @author Heshan Wanigasooriya <heshan at heidisoft.com><heshanmw@gmail.com> + * @todo */ /** * Implementation of hook_help(). */ -function video_image_help($section) { - switch ($section) { +function video_image_help($path, $arg) { + switch ($path) { case 'admin/modules#description': - return t('Enable thumbnails support for video module.'); + return t('Enable thumbnail support for video module.'); } } /** * Implementation of hook_menu() */ -function video_image_menu($may_cache) { +function video_image_menu() { $items = array(); + $may_cache=true; if ($may_cache) { - $items[] = array( - 'path' => 'admin/content/video/image', - 'title' => t('Video image'), - 'description' => t('Administer video_image module settings'), - 'callback' => 'drupal_get_form', - 'callback arguments' => array('video_image_admin_settings'), - 'access' => user_access('administer site configuration'), + $items['admin/settings/video/image'] = array( + 'title' => 'Video image', + 'description' => 'Administer video_image module settings', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('video_image_admin_settings'), + 'access arguments' => array('administer site configuration'), 'type' => MENU_NORMAL_ITEM, ); } @@ -40,14 +42,21 @@ function video_image_menu($may_cache) { /** + * Implementation of hook_perm + */ +function video_image_perm() { + $array = array('override autothumbnailing using uploaded image'); + return $array; +} + + +/** * Settings form */ function video_image_admin_settings() { - if (module_exists('video_upload')) { - if (variable_get('video_image_auto_thumbnail', 0)) { - $upload_weight = db_result(db_query("SELECT weight FROM {system} WHERE name='video_upload'")); - db_query("UPDATE {system} SET weight=".($upload_weight+1)." WHERE name='video_image'"); - } + if (module_exists('video_upload') && variable_get('video_image_auto_thumbnail', 0)) { + $upload_weight = db_result(db_query("SELECT weight FROM {system} WHERE name='video_upload'")); + db_query("UPDATE {system} SET weight=".($upload_weight+1)." WHERE name='video_image'"); } $form = array(); $form['video_image_publish_thumbnail'] = array( @@ -61,14 +70,68 @@ function video_image_admin_settings() { '#title' => t('Promote the thumbnails to the front page'), '#default_value' => _video_image_promote_thumbnails(), ); - + $form['autothumb'] = array( + '#type' => 'fieldset', + '#title' => t('Automatic video thumbnailing'), + '#collapsible' => TRUE, + '#collapsed' => FALSE, + '#description' => t('This feature requires the \'video_ffmpeg_helper\' module'), + ); + $auto_thumb_disable = !module_exists('video_ffmpeg_helper'); + $form['autothumb']['video_image_auto_thumbnail'] = array( + '#type' => 'checkbox', + '#title' => t('Auto thumbnail for videos'), + '#description' => t('If set up correctly, this will auto-generate a thumbnail for each video created.'), + '#default_value' => variable_get('video_image_auto_thumbnail', false) && !$auto_thumb_disable, + '#disabled' => $auto_thumb_disable, + ); + /* + $form['autothumb']['video_image_auto_thumbnail_only'] = array( + '#type' => 'checkbox', + '#title' => t('Use auto-thumbnailer exclusively for video images'), + '#description' => t('If checked, this will disable the file upload box for the user-supplied thumbnail. Only check this if you have checked to be sure that auto-thumbnailing works. Auto thumbnail must be selected for this to be enabled.'), + '#default_value' => variable_get('video_image_auto_thumbnail_only', false), + '#disabled' => !variable_get('video_image_auto_thumbnail', false), + ); + */ + $form['autothumb']['video_image_auto_thumbnail_debug'] = array( + '#type' => 'checkbox', + '#title' => t('Debug automatic thumbnail process'), + '#default_value' => variable_get('video_image_auto_thumbnail_debug', false), + '#description' => t('Automatic thumbnailing of videos is dependent on the actual video types. Some video types may not be able to be automatically thumbnailed. Setting this option will allow messages to be show when posting and editing of videos that can be automatically thumbnailed.'), + '#disabled' => $auto_thumb_disable, + ); + + return system_settings_form($form); } +function video_image_admin_settings_validate($form, &$form_state) { + if (module_exists('video_ffmpeg_helper')) { + if ($form_state['values']['video_image_auto_thumbnail']) { + $path_ok = _video_ffmpeg_helper_check_exe_path(); + if (!$path_ok) { + drupal_set_message(t('The path for \'ffmpeg\' is not valid. Please check settings on the !ffmpeg_settings_page', array('!ffmpeg_settings_page' => l(t('Video ffmpeg helper settings page'), 'admin/settings/video/ffmpeg_helper'))), 'error'); + } + } + } +} + + +/** + * Return true if the video support authothumbnailing +*/ +function video_image_is_autothumbable($node) { + $info = video_get_type_info($node->vtype); + $has_hook = module_hook('video_' . $node->vtype, 'v_auto_thumbnail'); + return $has_hook && isset($info[$node->vtype]['#autothumbable']) && $info[$node->vtype]['#autothumbable']; +} + + /** * Implementation of hook_form_alter() */ -function video_image_form_alter($form_id, &$form) { +function video_image_form_alter(&$form, &$form_state, $form_id) { if($form_id == 'video_node_form') { @@ -76,18 +139,37 @@ function video_image_form_alter($form_id, &$form) { $value = ($node->new_image) ? '#value' : '#default_value'; $form['iid'] = array('#type' => 'hidden', $value => $node->iid); - if (function_exists('_image_check_settings')) { - _image_check_settings(); + if (!is_array($node->tempimage['fids'])) { + $fids = array('_original' => 0); + foreach (_image_get_sizes() as $size) { + $fids[$size['label']] = 0; + } + $node->tempimage['fids'] = $fids; + } + $form['tempimage']['#tree'] = true; + foreach ($node->tempimage['fids'] as $label => $fid) { + $form['tempimage']['fids'][$label] = array('#type' => 'hidden', $value => $fid); + } + + $auto_thumbable = video_image_is_autothumbable($node); + + if(!$auto_thumbable || user_access('override autothumnailing using uploaded images')) { + // let's be sure that image directories are ready + if (function_exists('_image_check_settings')) { + _image_check_settings(); + } + // needed for uploading $form['#attributes'] = array("enctype" => "multipart/form-data"); - - $form['image'] = array('#type' => 'fieldset', '#title' => t('Image thumbnails'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#weight' => -17, '#description' => t('Use this form to upload an image.')); - + + $form['image'] = array('#type' => 'fieldset', '#title' => t('Image thumbnails'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#weight' => -17, '#description' => t('Upload an image to be used as the thumbnail for this video.')); + $form['image']['image'] = array('#type' => 'file', '#title' => t('Image')); - $form['image']['image_title'] = array('#type' => 'textfield', '#title' => t('Image title'), '#default_value' => $node->image->image_title); + } + if ($node->nid && $auto_thumbable) { + $form['regenerate_thumbnail'] = array('#type' => 'checkbox', '#title' => t('Auto regenerate thumbnail'), '#default_value' => 0); } } - } @@ -95,67 +177,31 @@ function video_image_form_alter($form_id, &$form) { * Implementation of hook_nodeapi() */ function video_image_nodeapi(&$node, $op, $teaser) { + //print_r($op); + //exit; if($node->type == 'video') { switch ($op) { - case 'load': - $output['iid'] = $node->serial_data['iid']; - return $output; - case 'submit': - if (variable_get('video_image_auto_thumbnail_debug', false) && variable_get('video_image_auto_thumbnail', false)) { - drupal_set_message(t('video_image_nodeapi: prepare: ready to thumbnail image')); - } - $field_name = file_check_upload('image'); - $image->uid = $node->uid; - $image->name = $node->name; - $image->created = $node->created; - $image->type = 'image'; - //$image->status = _video_image_publish_thumbnails(); - //$image->promote = _video_image_promote_thumbnails(); - if (!$field_name && module_exists('video_ffmpeg_helper') && variable_get('video_ffmpeg_helper_auto_thumbnail', false)) { - $image->title = $_SESSION['video_upload_file']->filename; - $field_name = _video_ffmpeg_helper_auto_thumbnail($node); - } - else { - $image->title = $_POST['edit']['image_title']; - $field_name = 'image'; - } - image_prepare($image, $field_name); - if ($image->images) { - node_validate($image); - if (!form_get_errors()) { - $image = node_submit($image); - node_save($image); - - // needed to set the correct status and promote values if the user does not have enought permissions. Is there a better solution??? - db_query('UPDATE {node} SET status = %d, promote = %d WHERE nid = %d AND vid = %d', _video_image_publish_thumbnails(), _video_image_promote_thumbnails(), $image->nid, $image->vid); - - $node->iid = $node->serial_data['iid'] = $image->nid; - $_SESSION['video_upload_file']->iid = $image->nid; - $node->new_image = TRUE; - } - } - else if (isset($_SESSION['video_upload_file']->iid)) { - $node->iid = $_SESSION['video_upload_file']->iid; - } + case 'load': + //exit; + return _video_image_load($node); - $node->serial_data['iid'] = $node->iid; - break; case 'prepare': - ; - break; + //exit; + _video_image_prepare($node); + break; + + case 'presave': + //exit; + _video_image_submit($node); + break; case 'view': - if ($node->iid) { - if($teaser) { - $node->content['video_image_thumbnail'] = array('#value' => theme('video_image_teaser', $node)); - } - else { - $node->content['video_image_thumbnail'] = array('#value' => theme('video_image_body', $node)); - } - } + //exit; + _video_image_view($node, $teaser); break; case 'delete': - node_delete(array('nid' => $node->iid)); + //exit; + _video_image_delete($node); break; } } @@ -163,51 +209,279 @@ function video_image_nodeapi(&$node, $op, $teaser) { /** - * Render the output for the node teaser. + * Renders thumbnail node with a link to the video node to be used on video teasers. * - * @param $node - * object with node information + * @param $image + * object with image node information + * @param $video + * the video node associated with image * * @return * string of content to display */ -function theme_video_image_teaser($node) { - if($node->serial_data['iid']) { - $image = node_load($node->serial_data['iid']); - $image = image_display($image, 'thumbnail', array('class' => 'video_image_teaser')); +function theme_video_image_teaser($image, $video) { + + $image_html = NULL; + + if($image != NULL && $image->type == 'image') { + $image_html = image_display($image, 'thumbnail', array('class' => 'video_image_teaser')); } - else { // only for backward compatibility - $image = theme('image', $node->serial_data['image_teaser'], $node->title, $node->title, array('class' => 'video_image_teaser'), FALSE); + else if($image_node == NULL && $video->serial_data['image_teaser']){ // only for backward compatibility + $image_html = theme('image', $video->serial_data['image_teaser'], $video->title, $video->title, array('class' => 'video_image_teaser'), FALSE); + } + + if($image) { + //Create a link with an image in it. + $output .= l($image_html, "node/$video->nid", array('html' => TRUE)); + $output .= '<br class="video_image_clear" />'; } - $output .= l($image, "node/$node->nid", array(), NULL, NULL, FALSE, TRUE); //Create a link with an image in it. - $output .= '<br class="video_image_clear" />'; return $output; } -/** - * Generates the image HTML displayed in the Node body. - * - * @param $node - * object with node information - * - * @return - * string of content to display - */ -function theme_video_image_body($node) { - if(variable_get('video_playinbody', 0) == 0){ - if($node->serial_data['iid']) { - $image = node_load($node->serial_data['iid']); - $image = image_display($image, 'thumbnail'); +/* nodeapi split out hooks */ +function _video_image_load(&$node) { + $output['iid'] = $node->serial_data['iid']; + return $output; +} + +function _video_image_prepare(&$node) { + // let's check that we have a valid image + //print_r($node); + //exit; + if (count($_POST)) { + + $validators = array( + 'file_validate_is_image' => array() + ); + + $field_name = file_save_upload('image', $validators); + if (!$field_name && video_image_is_autothumbable($node)) { + _video_image_thumbnail_debug(t('video_image_nodeapi: prepare: ready to thumbnail video')); + $field_name = module_invoke('video_' . $node->vtype, 'v_auto_thumbnail', $node); + if ($field_name === false && count($_POST)) { + drupal_set_message(t('The thumbnailing process of your video failed for some reason. Video thumbnail will not be available.'), 'error'); + } } - else { // only for backward compatibility - $image = theme('image', $node->serial_data['image_view'], $node->title, $node->title, array('class' => 'video_image_view'), FALSE); //Create image HTML + } + if ($field_name) { + $node->tempimage = _video_image_temp_image_store($field_name); + $node->new_image = TRUE; + } else if (is_array($_POST['tempimage']) && + ($_POST['op'] == 'Preview' || $_POST['op'] == 'Submit')) { + $node->tempimage = (array)_video_image_temp_image_load(array_values($_POST['tempimage']['fids'])); + } +} + +function _video_image_submit(&$node) { + //print_r($node); + //exit; + // ############# PREPARE ####################### + // ------------- MOVED ------------------------- + if (count($_POST)) { + + $validators = array( + 'file_validate_is_image' => array() + ); + + $field_name = file_save_upload('image', $validators); + if (!$field_name && video_image_is_autothumbable($node)) { + _video_image_thumbnail_debug(t('video_image_nodeapi: prepare: ready to thumbnail video')); + $field_name = module_invoke('video_' . $node->vtype, 'v_auto_thumbnail', $node); + if ($field_name === false && count($_POST)) { + drupal_set_message(t('The thumbnailing process of your video failed for some reason. Video thumbnail will not be available.'), 'error'); + } } - $output = l($image, "node/$node->nid/play", array('title' => t('play') . ' ' . $node->title), NULL, NULL, FALSE, TRUE); //Create link HTML with image in it. } - return $output; + + if ($field_name) { + /* + if($node->iid){ + + // Remove all the existing images. + $result = db_query("SELECT f.fid, f.filepath FROM {image} i INNER JOIN {files} f ON i.fid = f.fid WHERE i.nid = %d", $node->iid); + while ($file = db_fetch_object($result)) { + file_delete(file_create_path($file->filepath)); + db_query("DELETE FROM {files} WHERE fid = %d", $file->fid); + } + //db_query("DELETE FROM {image} WHERE nid = %d", $node->iid); + } + * + */ + $node->tempimage = _video_image_temp_image_store($field_name); + $node->new_image = TRUE; + //print_r($node); + //die; + } else if (is_array($_POST['tempimage']) && ($_POST['op'] == 'Preview' || $_POST['op'] == 'Submit')) { + //print_r($node); + //exit; + $node->tempimage = (array)_video_image_temp_image_load(array_values($_POST['tempimage']['fids'])); + } + + // ########################################################################### + + + if ($node->regenerate_thumbnail) { + _video_image_regenerate_thumbnail($node); + } + if (is_array($node->tempimage['fids']) && $node->tempimage['fids']['_original']) { + $image = _video_image_temp_image_load(array_values($node->tempimage['fids'])); + //print_r($image); + //exit; + db_query("DELETE FROM {files} WHERE fid in (%s)", + implode(',', array_values($node->tempimage['fids']))); + // initialize standard node fields + //print_r($image); + //exit; + $image->uid = $node->uid; + $image->created = time(); + $image->title = t('Video thumbnail for !title', array('!title' => $node->title)); + $image = node_submit($image); + $image->uid = $node->uid; + $image->status = _video_image_publish_thumbnails(); + $image->promote = _video_image_promote_thumbnails(); + // This is a messages hack (we don't want to see what happens under the covers) + _video_image_pause_messages(true); + if ($node->iid) { + + $oldimage = node_load($node->iid); + $oldimage->images = $image->images; + + // delete the old images? + $oldimage->new_image = 1; + node_save($oldimage); + $node->iid = $oldimage->nid; + $node->serial_data['iid'] = $node->iid; + } else { + node_save($image); + + //print_r($image); + //exit; + //image_insert($image); + $node->iid = $image->nid; + // store the iid into the serial_data + $node->serial_data['iid'] = $node->iid; + //print_r($node); + //die; + // needed to set the correct status and promote values even if the user does not have enough permissions. Is there a better solution??? + // db_query('UPDATE {node} SET status = %d, promote = %d WHERE nid = %d AND vid = %d', _video_image_publish_thumbnails(), _video_image_promote_thumbnails(), $image->nid, $image->vid); + } + _video_image_pause_messages(); + } + else { + $node->serial_data['iid'] = $node->iid; + } +} + +function _video_image_view(&$node, $teaser) { + if (is_array($node->tempimage['fids']) && $node->tempimage['fids']['_original']) { + $image = _video_image_temp_image_load(array_values($node->tempimage['fids'])); + } else if ($node->iid) { + $image = node_load($node->iid); + } else { + $image = NULL; // this is for backward compatibility + } + + if($teaser) { + $node->content['video_image_thumbnail'] = array('#value' => theme('video_image_teaser', $image, $node)); + } } +function _video_image_regenerate_thumbnail(&$node) { + $field_name = module_invoke('video_' . $node->vtype, 'v_auto_thumbnail', $node); + if ($field_name) { + $node->tempimage = _video_image_temp_image_store($field_name); + $node->new_image = TRUE; + } +} + +function _video_image_delete(&$node) { + _video_image_pause_messages(true); + node_delete(array('nid' => $node->iid)); + _video_image_pause_messages(); +} + +/* At times, when doing sub-node processing (creating/deleting thumbnail nodes) + * we don't really want to show all the messages through to the end user or it + * gets a little bit confusing (image created messages when creating a video) + * so we suppress the messages with this procedure. + */ +function _video_image_pause_messages($snapshot = false) { + static $messages = null; + if ($snapshot) { + $messages = drupal_get_messages(); + } else if (is_array($messages)) { + $_SESSION['messages'] = $messages; + $messages = null; + } +} + +/* debugging framework for troublesome thumbnailing */ +function _video_image_thumbnail_debug($msg) { + static $debug = NULL; + if ($debug == NULL) { + $debug = variable_get('video_image_auto_thumbnail_debug', false); + } + if ($debug) { + $t = debug_backtrace(); + $l = array_shift($t); + drupal_set_message(basename($l['file'], '.module').': '.$msg); + } +} + +function _video_image_temp_image_store(&$file) { + $image = new stdClass(); + $image->images[IMAGE_ORIGINAL] = $file->filepath; + $image->images =_image_build_derivatives($image); + $image->type = 'image'; + $image->uid = 1; + $image->created = time(); + $image->title = t('video image thumbnail'); + // We're good to go. + + $image->rebuild_images = FALSE; + $image->new_file = TRUE; + + + //print_r($image); + //exit; + if ($image->images) { + node_validate($image); + if (!form_get_errors()) { + // save the images in the files table + foreach ($image->images as $l => $f) { + $info = image_get_info($f); + $file->fid = db_last_insert_id('files','fid'); + if($l=="_original"){ + db_query("INSERT INTO {files} (fid, filename, filepath, filemime, filesize) VALUES (%d, '%s', '%s', '%s', '%s')", + $fid, "video_image_temp.$l", $f, $info['mime_type'], $info['file_size']); + } + $image->fids[$l] = $file->fid; + } + } + } + //print_r($image); + //exit; + return (array)$image; +} + +/* Create a fake node object that acts like an image node + * by looking up each file in the array $fids and loading + * them into the images array. + */ +function _video_image_temp_image_load($fids) { + $image = new stdClass(); + $image->type = 'image'; + $image->new_file = 1; + $fids = implode(',', $fids); + $results = db_query("SELECT fid, filename, filepath FROM {files} WHERE fid IN (%s)", $fids); + while ($file = db_fetch_object($results)) { + $label = substr($file->filename, 17); + $image->images[$label] = $file->filepath; + $image->fids[$label] = $file->fid; + } + return $image; +} /* If the user has set a promote preference, use that, otherwise return * if 'promote' is set in the drupal content type settings @@ -238,4 +512,42 @@ function _video_image_publish_thumbnails() { } return $settings_override; } -?> + + +/** + * Create an image file object from a given image url +*/ +function _video_image_get_thumb_file_object($thumbnail_url, $id) { + + if($thumbnail_url && $thumbnail_url != '' && $image = image_gd_open($thumbnail_url, 'jpeg')) { + // save image to temp directory for processing + $location = file_directory_temp() .'/'. $id .'.jpg'; + image_gd_close($image, $location, 'jpeg'); + + + // get info and build a file object + $filepath = file_create_path($location, file_directory_temp()); + $info = image_get_info($filepath); + + $file = new stdClass(); + $file->filepath = realpath($filepath); + $file->filename = basename($file->filepath); + $file->filesize = $info['file_size']; + $file->filemime = $info['mime_type']; + + return $file; + } + + return null; +} + +/** + * Implementation of hook_theme(). + */ +function video_image_theme() { + return array( + 'video_image_teaser' => array( + 'arguments' => array('image' => NULL,'video' => NULL), + ), + ); +} |