Flash node lets you create nodes that store a piece of Flash animation. You can use it in a basic mode, where the Flash item is always displayed at the start of the node, but you can choose whether to have the Flash element displayed in both the teaser and the body, just the teaser, or just the body. You can define the height and width of the Flash element, or you can let the node use the Flash content\'s original settings.

The module also defines a new input filter called flash that you can use. This lets you re-use Flash content in other nodes by using the format [flash|nid=<nid>] in the body of a node. You can pass optional parameters to manipulate the display of the Flash content by including them in the macro. Allowable parameters are:

For example, to use Flash content from node 10, scaled to 50% of its original size, and with CSS class flash-left you would use [flash|nid=10|scale=0.5|class=flash-left]

Flash content is inserted using the method that you specify in SWFTools.'); } } /** * Implementation of hook_node_info */ function flashnode_node_info() { return array( 'flashnode' => array( 'name' => t('Flash'), 'module' => 'flashnode', 'description' => t('Allows you to easily upload and display a Flash file. You can choose whether the animation appears in the teaser, the body, or both.'), ), ); } /** * Implementation of hook_perm */ function flashnode_perm() { return array( 'create flash nodes', 'edit own flash nodes', 'administer flash node', 'hide display options', 'hide basic options', 'hide advanced options', 'import flash', ); } /** * Implementation of hook_access */ function flashnode_access($op, $node) { global $user; if ($op == 'create' && user_access('create flash nodes')) { return TRUE; } if ($op == 'update' || $op == 'delete') { if (user_access('edit own flash nodes') && ($user->uid == $node->uid)) { return TRUE; } } } /** * Implementation of hook_menu */ function flashnode_menu($may_cache) { $items = array(); if ($may_cache) { $items[] = array( 'path' => 'node/add/flashnode', 'title' => t('Flash'), 'access' => user_access('create flash nodes'), ); $items[] = array( 'path' => 'admin/settings/flashnode', 'title' => t('Flash node'), 'callback' => 'drupal_get_form', 'callback arguments' => array('flashnode_admin_settings'), 'access' => user_access('administer flash node'), 'type' => MENU_NORMAL_ITEM, 'description' => t('Set the directory where flash files are uploaded to.'), ); $items[] = array( 'path' => 'admin/content/flashnode', 'title' => t('Import Flash'), 'callback' => 'flashnode_import', 'access' => user_access('import flash'), 'description' => t('Import and create nodes from files that have been uploaded directly to the server.'), ); } return $items; } /** * Implements hook_cron (delete old temp files) */ function flashnode_cron() { $path = variable_get('flashnode_default_path', 'flash') . '/temp'; $files = file_scan_directory(file_create_path($path), '.*'); foreach ($files as $file => $info) { if (time() - filemtime($file) > 60*60*6) { file_delete($file); } } } /** * Implementation of hook_prepare(). */ function flashnode_prepare(&$node) { $field_name = 'flashfile'; // check if the upload is valid if ($file = file_check_upload($field_name)) { // Spaces can cause problems, so replace them with underscores $file->filename = str_replace(' ', '_', $file->filename); // Modification as swftools seems to be prepending the files directory by itself // and this has broken the preview function. Path needs to be stored just as // flash/movie.swf or flash/temp/movie.swf to avoid files/files/flash/movie.swf $swf_path_fix = _flashnode_filename($file->filename, TRUE); // if it is then save it to the flash/temp folder $file = file_save_upload($field_name, $swf_path_fix); // if the upload succeeds... if ($file) { // ...check to see we have either a flash movie, and flv, or an mp3 $file_mime = strtolower($file->filemime); $file_ext = strtolower(substr(strrchr($file->filename, '.'), 1)); if (strpos(trim(variable_get('flashnode_allowable_types', 'swf flv mp3')), $file_ext) === false) { watchdog($field_name,t('Flash node was given %type for upload.', array('%type' => $file_ext))); form_set_error($field_name, t('The specified file is not an allowed format.')); // delete the uploaded file in case it is unsafe file_delete($file->filepath); return; } } else { return; } // add data to the $node->flashnode object $node->flashnode['_flashnode'] = $swf_path_fix; $node->flashnode['filemime'] = $file->filemime; $node->new_file = TRUE; // If upload is not swf, remind user to set movie size if ($file_ext != 'swf') { drupal_set_message(t('Remember you might have to set the movie size for flv or mp3 files as flash node cannot always automatically determine the player size!'), 'warning'); } } // try to get the file settings for this file, using image_get_info $info = image_get_info(file_create_path($node->flashnode['_flashnode'])); $node->flashnode['_height'] = $info['height']; $node->flashnode['_width'] = $info['width']; // If the height and width settings are not available to this user then reset them everytime we get a new file // Otherwise the height/width will be locked to the first file that is uploaded global $user; if (user_access('hide basic options') && ($user->uid != 1)) { unset($node->flashnode['height']); unset($node->flashnode['width']); } } /** * Implementation of hook_validate */ function flashnode_validate(&$node, $form) { // Check if file is empty if (empty($form['flashnode']['_flashnode']['#value'])) { form_set_error('flashfile', t('You must specify a Flash file to upload.')); } // Check height is valid (not empty & not numeric) if (!is_numeric($form['flashnode']['options']['height']['#value']) && !empty($form['flashnode']['options']['height']['#value'])) { form_set_error('flashnode][height', t('You must enter a valid height.')); } // Check width is valid (not empty & not numeric) if (!is_numeric($form['flashnode']['options']['width']['#value']) && !empty($form['flashnode']['options']['width']['#value'])) { form_set_error('flashnode][width', t('You must enter a valid width.')); } } /** * Implementation of hook_form */ function flashnode_form(&$node, &$param) { // Need to access user object to determine visibility of basic and advanced settings global $user; // Check folders exist and are writable _flashnode_check_settings(); // Begin form construct $form['#attributes'] = array("enctype" => "multipart/form-data"); $form['flashnode']['#tree'] = TRUE; // Lifted from image.module to handle upload and previews - not sure why this works! if ($node->new_file) { $form['new_file'] = array('#type' => 'value', '#value' => TRUE); } if ($node->new_file) { $form['flashnode']['_flashnode'] = array('#type' => 'hidden', '#value' => $node->flashnode['_flashnode']); $form['flashnode']['filemime'] = array('#type' => 'hidden', '#value' => $node->flashnode['filemime']); $form['flashnode']['_height'] = array('#type' => 'hidden', '#value' => $node->flashnode['_height']); $form['flashnode']['_width'] = array('#type' => 'hidden', '#value' => $node->flashnode['_width']); } else { $form['flashnode']['_flashnode'] = array('#type' => 'hidden', '#default_value' => $node->flashnode['_flashnode']); $form['flashnode']['filemime'] = array('#type' => 'hidden', '#default_value' => $node->flashnode['filemime']); $form['flashnode']['_height'] = array('#type' => 'hidden', '#default_value' => $node->flashnode['_height']); $form['flashnode']['_width'] = array('#type' => 'hidden', '#default_value' => $node->flashnode['_width']); } // Title and body fields - this code from node_content_form() in node.module $type = node_get_types('type', $node); if ($type->has_title) { $form['title'] = array( '#type' => 'textfield', '#title' => check_plain($type->title_label), '#required' => TRUE, '#default_value' => $node->title, '#weight' => -5, ); } if ($type->has_body) { $form['body_filter']['body'] = array( '#type' => 'textarea', '#title' => check_plain($type->body_label), '#default_value' => $node->body, '#rows' => 20, '#required' => ($type->min_word_count > 0)); $form['body_filter']['format'] = filter_form($node->format); } // Flash node upload field $form['flashnode']['flashfile'] = array( '#type' => 'file', '#title' => t('Flash file'), '#description' => t('Click "Browse..." to select a swf, flv or mp3 file to upload.'), '#tree' => FALSE, '#after_build' => array('_flashnode_form_after_build'), ); // Put other settings in a collapsible set for a clean input form // We actually create two sections - basic and advance to shield basic users from complex stuff // that they don't need to see! $form['flashnode']['options1'] = array( '#type' => 'fieldset', '#title' => t('Basic flash node options'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#tree' => FALSE, '#access' => !user_access('hide basic options') || ($user->uid == 1), ); // We over-ride the #parents setting here to strip out ['options'] $form['flashnode']['options1']['display'] = array( '#type' => 'radios', '#title' => t('Display in'), '#default_value' => isset($node->flashnode['display']) ? $node->flashnode['display'] : variable_get('flashnode_default_display', 0), '#options' => array( 0 => t('Teaser and body'), 1 => t('Teaser only'), 2 => t('Body only'), 3 => t('Do not display'), ), '#parents' => array('flashnode', 'display'), '#access' => !user_access('hide display options') || ($user->uid == 1), ); // We over-ride the #parents setting here to strip out ['options'] $form['flashnode']['options1']['width'] = array( '#type' => 'textfield', '#title' => t('Width'), '#default_value' => $node->flashnode['width'], '#size' => 5, '#maxlength' => 5, '#description' => t('The width of the movie, in pixels. Leave blank to use the file\'s own settings.'), '#parents' => array('flashnode', 'width'), '#after_build' => array('_flashnode_form_after_build'), ); // We over-ride the #parents setting here to strip out ['options'] $form['flashnode']['options1']['height'] = array( '#type' => 'textfield', '#title' => t('Height'), '#default_value' => $node->flashnode['height'], '#size' => 5, '#maxlength' => 5, '#description' => t('The height of the movie, in pixels. Leave blank to use the file\'s own settings.'), '#parents' => array('flashnode', 'height'), '#after_build' => array('_flashnode_form_after_build'), ); // Put other settings in a collapsible set for a clean input form // We actually create two sections - basic and advance to shield basic users from complex stuff // that they don't need to see! $form['flashnode']['options2'] = array( '#type' => 'fieldset', '#title' => t('Advanced flash node options'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#tree' => FALSE, '#access' => !user_access('hide advanced options') || ($user->uid == 1), ); // We over-ride the #parents setting here to strip out ['options'] $form['flashnode']['options2']['substitution'] = array( '#type' => 'textarea', '#title' => t('Substitution content'), '#rows' => 5, '#default_value' => $node->flashnode['substitution'], '#parents' => array('flashnode', 'substitution'), '#description' => t('If a javascript method is used to embed flash then this is the content that users will see if they are unable to, or choose not to, display the flash content. This content uses the same input format as the body. The default content may be used by entering @default.', array('@default' => '!default')), '#after_build' => array('_flashnode_form_after_build'), ); // We over-ride the #parents setting here to strip out ['options'] $form['flashnode']['options2']['flashvars'] = array( '#type' => 'textarea', '#title' => t('Flashvars'), '#rows' => 5, '#default_value' => $node->flashnode['flashvars'], '#parents' => array('flashnode', 'flashvars'), '#description' => t('Specify any flashvars that need to be passed to the movie. If the input format allows PHP code you may use PHP to create a dynamic flashvars string.') ); // We over-ride the #parents setting here to strip out ['options'] $form['flashnode']['options2']['base'] = array( '#type' => 'textfield', '#title' => t('Base'), '#default_value' => $node->flashnode['base'] ? $node->flashnode['base'] : variable_get('flashnode_default_base', base_path().file_directory_path()), '#parents' => array('flashnode', 'base'), '#description' => t('Over-ride the default setting with a different base path here if necessary, e.g. if migrating existing content. This setting is only needed for movies that use the %loadmovie command with relative paths.', array('%loadmovie' => 'loadMovie()')), ); // Need to call the _flashnode_form_after_build function $form['flashnode']['#after_build'] = array('_flashnode_form_after_build'); // Return form return $form; } /** * Implementation of hook_load */ function flashnode_load(&$node) { // Get the flash file associated with this node, it has filename _flash $result = db_query("SELECT filepath FROM {files} WHERE nid=%d AND filename='%s'", $node->nid, '_flashnode'); $node->flashnode['_flashnode'] = db_result($result); // Retrieve parameters associated with this file from flash table $result = db_query("SELECT height, width, display, substitution, flashvars, base FROM {flashnode} WHERE nid=%d", $node->nid); // Store all the settings in to the $node->flashnode object $settings = db_fetch_object($result); foreach ($settings as $parameter => $value) { $node->flashnode[$parameter] = $value; } } /** * Implementation of hook_insert */ function flashnode_insert($node) { // Regular insert - came from node generation form if (!$node->flashnode['import']) { // Call helper to do file copy, supply the nid, and the path and mime type of the current file $fid = _flashnode_insert($node->nid, file_create_path($node->flashnode['_flashnode']), $node->flashnode['filemime'], $node->flashnode['import']); } // If an fid was returned _flashnode_insert succeeded if ($fid) { // Update the flash table with the relevant data db_query("INSERT INTO {flashnode} (nid, vid, height, width, display, substitution, flashvars, base, fid) VALUES (%d, %d, %d, %d, %d, '%s', '%s', '%s', %d)", $node->nid, $node->vid, $node->flashnode['height'], $node->flashnode['width'], $node->flashnode['display'], $node->flashnode['substitution'], $node->flashnode['flashvars'], $node->flashnode['base'], $fid); } } /** * Implementation of hook_update */ function flashnode_update($node) { // Get the path of the old file $old_path = db_result(db_query("SELECT filepath FROM {files} WHERE filename='%s' AND nid=%d", '_flashnode', $node->nid)); // This is a new file if the old path and the current path differ... if ($old_path != $node->flashnode['_flashnode']) { // ...so delete the old path file_delete(file_create_path($old_path)); // Delete the entries for the old file from the database db_query("DELETE FROM {files} WHERE filename='%s' AND nid=%d", '_flashnode', $node->nid); db_query("DELETE FROM {flashnode} WHERE nid=%d", $node->nid); // Call flashnode_insert to create the new entry flashnode_insert($node); } else { // We still have the same file, but we have some new settings to update in the database db_query("UPDATE {flashnode} SET height=%d, width=%d, display=%d, substitution='%s', flashvars='%s', base='%s', vid=%d WHERE nid=%d", $node->flashnode['height'], $node->flashnode['width'], $node->flashnode['display'], $node->flashnode['substitution'], $node->flashnode['flashvars'], $node->flashnode['base'], $node->vid, $node->nid); } // Reset the cache to ensure any pages using filters are updated cache_clear_all('*', 'cache_filter', true); } /** * Implementation of hook_delete. */ function flashnode_delete($node) { // Delete the file // Note use of file_create_path, files are stored with only flash/ prepended so has to be qualified file_delete(file_create_path($node->flashnode['_flashnode'])); // Delete the relevant entries from the database db_query("DELETE FROM {files} WHERE filename='%s' AND nid=%d", '_flashnode', $node->nid); db_query("DELETE FROM {flashnode} WHERE nid=%d", $node->nid); } /** * Implementation of hook_view */ function flashnode_view($node, $teaser, $page = 0) { // Run through the filters before adding in code, so that