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:
Flash content is inserted using a technique called unobtrusive flash object. This uses a small piece of javascript to put the Flash content on the page in a way that leaves the page compliant with XHTML standards. Older browsers, or devices that don\'t understand javascript or Flash, will see a piece of text explaining that the Flash content is missing.', array( '!flashurl' => 'http://en.wikipedia.org/wiki/Macromedia_Flash', '!ufourl' => 'http://www.bobbyvandersluis.com/ufo')); } } /** * Implementation of hook_node_info */ function flash_node_info() { return array( 'flash' => array( 'name' => t('Flash'), 'module' => 'flash', 'description' => t('Allows you to upload a Flash file. You can choose whether the animation appears in the teaser, the body, or both.'), ), ); } /** * Implementation of hook_perm */ function flash_perm() { return array( 'create flash', 'edit own flash', 'administer flash', ); } /** * Implementation of hook_access */ function flash_access($op, $node) { global $user; if ($op == 'create' && user_access('create flash')) { return TRUE; } if ($op == 'update' || $op == 'delete') { if (user_access('edit own flash') && ($user->uid == $node->uid)) { return TRUE; } } } /** * Implementation of hook_menu */ function flash_menu($may_cache) { $items = array(); if ($may_cache) { $items[] = array( 'path' => 'node/add/flash', 'title' => t('Flash'), 'access' => user_access('create flash'), ); $items[] = array( 'path' => 'admin/settings/flash', 'title' => ('Flash node settings'), 'callback' => 'drupal_get_form', 'callback arguments' => array('flash_admin_settings'), 'access' => user_access('administer flash'), 'type' => MENU_NORMAL_ITEM, 'description' => t('Tell Drupal where to store Flash files, and specify the default minimum Flash player version.'), ); } return $items; } /** * Implementation of hook_nodeapi(). */ function flash_nodeapi(&$node, $op, $arg) { switch ($op) { case 'view': static $ufo_added = FALSE; /** * at the moment we add ufo.js to all pages * think this could be amended using a reg_ex to examine the node to see * if the js is required. To do later! */ if (!$ufo_added) { // insert ufo.js in to the page header $flash_script = drupal_get_path('module', 'flash').'/ufo.js'; drupal_add_js($flash_script); $ufo_added = TRUE; } } } /** * Implements hook_cron (delete old temp files) */ function flash_cron() { $path = variable_get('flash_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 flash_prepare(&$node, $field_name) { if (is_null($field_name)) { $field_name = 'flashfile'; } // check if the upload is valid if ($file = file_check_upload($field_name)) { // if it is then save it to the flash/temp folder $file = file_save_upload($field_name, _flash_filename($file->filename, TRUE)); // if the upload succeeds... if ($file) { // ...check if the mime type wasn't flash if (strtolower($file->filemime) != 'application/x-shockwave-flash') { watchdog($field_name,t('flash was given %type for upload.', array('%type' => $node->file->filemime))); form_set_error($field_name, t('The specified file is not a valid Flash format.')); // delete the uploaded file in case it is unsafe file_delete($file->filepath); return; } } else { return; } // add data to the $node->flash object $node->flash['_flash'] = $file->filepath; $node->flash['filemime'] = $file->filemime; $node->new_file = TRUE; } // try to get the file settings for this file, using image_get_info $info = image_get_info(file_create_path($node->flash['_flash'])); $node->flash['_height'] = $info['height']; $node->flash['_width'] = $info['width']; } /** * Implementation of hook_validate */ function flash_validate(&$node, $form) { // Check if file is empty if (empty($form['flashfile']['#value']) && empty($form['flash']['_flash']['#value'])) { form_set_error('flashfile', t('You must specify a Flash file to upload.')); } // check all settings have achieved a numeric value $settings = array('height','width','version','build'); foreach($settings as $label) { if (!is_numeric($form['flash']['options'][$label]['#value']) && !empty($form['flash']['options'][$label]['#value'])) { form_set_error('flash]['.$label, t('You must enter a valid @label.', array('@label' => $label))); } } } /** * Implementation of hook_form */ function flash_form(&$node, &$param) { // check folders exist and are writable _flash_check_settings(); // begin form construct $form['#attributes'] = array("enctype" => "multipart/form-data"); $form['flash']['#tree'] = TRUE; // lifted from image.module if ($node->new_file) { $form['new_file'] = array('#type' => 'value', '#value' => TRUE); } if ($node->new_file) { $form['flash']['_flash'] = array('#type' => 'hidden', '#value' => $node->flash['_flash']); $form['flash']['filemime'] = array('#type' => 'hidden', '#value' => $node->flash['filemime']); $form['flash']['_height'] = array('#type' => 'hidden', '#value' => $node->flash['_height']); $form['flash']['_width'] = array('#type' => 'hidden', '#value' => $node->flash['_width']); } else { $form['flash']['_flash'] = array('#type' => 'hidden', '#default_value' => $node->flash['_flash']); $form['flash']['filemime'] = array('#type' => 'hidden', '#default_value' => $node->flash['filemime']); $form['flash']['_height'] = array('#type' => 'hidden', '#default_value' => $node->flash['_height']); $form['flash']['_width'] = array('#type' => 'hidden', '#default_value' => $node->flash['_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); } $form['flash']['flashfile'] = array( '#type' => 'file', '#title' => t('Flash file'), '#description' => t('Click "Browse..." to select a Flash file to upload.'), '#tree' => FALSE, '#after_build' => array('_flash_form_after_build'), ); // Put other settings in a collapsible set for a clean input form $form['flash']['options'] = array( '#type' => 'fieldset', '#title' => t('Flash node options'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#tree' => FALSE, ); $form['flash']['options']['display'] = array( '#type' => 'radios', '#title' => t('Display in'), '#default_value' => $node->flash['display'] ? $node->flash['display'] : 0, '#options' => array( 0 => t('Teaser and body'), 1 => t('Teaser only'), 2 => t('Body only'), ), '#parents' => array('flash', 'display'), ); $form['flash']['options']['width'] = array( '#type' => 'textfield', '#title' => t('Width'), '#default_value' => $node->flash['width'], '#size' => 5, '#maxlength' => 5, '#description' => t('The width of the movie, in pixels. Leave blank to use the file\'s own settings.'), '#after_build' => array('_flash_form_after_build'), '#parents' => array('flash', 'width'), ); $form['flash']['options']['height'] = array( '#type' => 'textfield', '#title' => t('Height'), '#default_value' => $node->flash['height'], '#size' => 5, '#maxlength' => 5, '#description' => t('The height of the movie, in pixels. Leave blank to use the file\'s own settings.'), '#after_build' => array('_flash_form_after_build'), '#parents' => array('flash', 'height'), ); $form['flash']['options']['version'] = array( '#type' => 'textfield', '#title' => t('Flash version required'), '#default_value' => $node->flash['version'] ? $node->flash['version'] : variable_get('flash_version',6), '#size' => 5, '#maxlength' => 5, '#description' => t('The minimum Flash version required to play this movie. Leave blank to reset to the default.'), '#after_build' => array('_flash_form_after_build'), '#parents' => array('flash', 'version'), ); $form['flash']['options']['build'] = array( '#type' => 'textfield', '#title' => t('Flash build required'), '#default_value' => ($node->flash['build'] != '') ? $node->flash['build'] : variable_get('flash_build',0), '#size' => 5, '#maxlength' => 5, '#description' => t('The minimum Flash build required to play this movie. Leave blank to reset to the default.'), '#after_build' => array('_flash_form_after_build'), '#parents' => array('flash', 'build'), ); return $form; } /** * Various functions to manipulate the form after building in case default * values are being reset. It also changes the description on the flash file * field when a file has been uploaded, to help the user to identify which file * is in use on this node. #parents is used as the identified in case the title * is being translated. Not sure if this is the right way to achieve this, but * it appears to work! */ function _flash_form_after_build($form, $form_values) { // Change file upload description to reflect current upload if there is one if (!empty($form_values['flash']['_flash']) && $form['#parents'][0] == 'flashfile') { $form['#description'] = t('Current file is %filename. Click "Browse..." to upload a different file.', array('%filename' => basename($form_values['flash']['_flash']))); } // If width field is empty then reset it to the default width if (empty($form_values['flash']['width']) && $form['#parents'][1] == 'width') { $form['#value'] = $form_values['flash']['_width']; form_set_value($form, $form_values['flash']['_width']); } // If height field is empty then reset it to the default height if (empty($form_values['flash']['height']) && $form['#parents'][1] == 'height') { $form['#value'] = $form_values['flash']['_height']; form_set_value($form, $form_values['flash']['_height']); } // If version field is empty then reset it to the default height if (empty($form_values['flash']['version']) && $form['#parents'][1] == 'version') { $form['#value'] = variable_get('flash_version', 6); form_set_value($form, variable_get('flash_version', 6)); } // If version field is empty then reset it to the default height if (empty($form_values['flash']['build']) && $form['#parents'][1] == 'build') { $form['#value'] = variable_get('flash_build', 0); form_set_value($form, variable_get('flash_build', 0)); } // Return the amended form element return $form; } /** * Implementation of hook_load */ function flash_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, '_flash'); $node->flash['_flash'] = db_result($result); // retrieve parameters associated with this file from flash table $result = db_query("SELECT height, width, version, build, display FROM {flash} WHERE nid=%d", $node->nid); // store all the settings in to the $node->flash object $settings = db_fetch_object($result); foreach ($settings as $parameter => $value) { $node->flash[$parameter] = $value; } } /** * Implementation of hook_insert */ function flash_insert($node) { // call helper to do file copy, supply the nid, and the path and mime type of the current file $fid = _flash_insert($node->nid, file_create_path($node->flash['_flash']), $node->flash['filemime']); // if an fid was returned _flash_insert succeeded if ($fid) { // update the flash table with the relevant data db_query("INSERT INTO {flash} (nid, height, width, version, build, display) VALUES (%d, %d, %d, %d, %d, %d)", $node->nid, $node->flash['height'], $node->flash['width'], $node->flash['version'], $node->flash['build'], $node->flash['display']); } } /** * Implementation of hook_update */ function flash_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", '_flash', $node->nid)); // This is a new file if the old path and the current path differ... if ($old_path != $node->flash['_flash']) { // ...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", '_flash', $node->nid); db_query("DELETE FROM {flash} WHERE nid=%d", $node->nid); // call flash_insert to create the new entry flash_insert($node); } else { // we still have the same file, but we have some new settings to update in the database db_query("UPDATE {flash} SET height=%d, width=%d, version=%d, build=%d, display=%d WHERE nid=%d", $node->flash['height'], $node->flash['width'], $node->flash['version'], $node->flash['build'], $node->flash['display'], $node->nid); } // reset the cache to ensure any pages using filters are updated cache_clear_all('*', 'cache_filter', true); } /** * Implementation of hook_delete. */ function flash_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->flash[_flash])); // delete the relevant entries from the database db_query("DELETE FROM {files} WHERE filename='%s' AND nid=%d", '_flash', $node->nid); db_query("DELETE FROM {flash} WHERE nid=%d", $node->nid); } /** * Implementation of hook_view */ function flash_view($node, $teaser, $page = 0) { // run through the filters before adding in code, so that ',array('!movie' => base_path().file_create_path($file['_flash']), '!flash_dir' => $flash_dir, '!height' => $file['height'], '!width' => $file['width'], '!version' => $file['version'], '!build' => $file['build'], '!id' => $div_id, '!options' => $options)); // increment the div counter in case there is more flash to show $div_count += 1; // return the HTML return $output; } /** * Verify the flash folders exist */ function _flash_check_settings() { // check for ufo.js (assume that if this is missing then so is ufo.swf) if (!file_exists(drupal_get_path('module', 'flash') . '/ufo.js')) { drupal_set_message(t('The required files ufo.js and ufo.swf are not available. You must !ufo and copy them to the flashnode module directory in order for flashnode to work. Refer to the flashnode README.txt file for more details.', array('!ufo' => 'download them'))); } // build the two relevant paths $flash_path = file_create_path(variable_get('flash_default_path', 'flash')); $temp_path = $flash_path . '/temp'; // check they exist, create if not file_check_directory($flash_path, FILE_CREATE_DIRECTORY, 'flash_default_path'); file_check_directory($temp_path, FILE_CREATE_DIRECTORY, 'flash_default_path'); } /** * Creates a flash filename */ function _flash_filename($filename, $temp = FALSE) { // get the flash path $result = variable_get('flash_default_path', 'flash').'/'; // if this is a temporary file, append temp if ($temp) { $result .= 'temp/'; } // add the filename to build the path $result .= $filename; // return the result return $result; } /** * Moves temporary file to flash directory and stores information in {files} */ function _flash_insert($nid, $flash, $mime) { // create the destination path and filename from the current name $dest = _flash_filename(basename($flash)); // try to move the flash file to the flash folder, auto renames if it already exists if (file_copy($flash, $dest)) { // add file data to $node->file $file->filename = '_flash'; $file->filepath = _flash_filename(basename($flash)); $file->filemime = $mime; // note use of file_create_path, files are stored with only flash/ prepended so has to be qualified $file->filesize = filesize(file_create_path($dest)); // create new record in files table $fid = db_next_id('{files}_fid'); db_query("INSERT INTO {files} (fid, nid, filename, filepath, filemime, filesize) VALUES (%d, %d, '%s', '%s', '%s', '%s')", $fid, $nid, $file->filename, $file->filepath, $file->filemime, $file->filesize); // return the assigned fid return $fid; } } /** * Function to retrive and inject flash, based on an array of arguments */ function flash_content($args = array()) { // if no $args['nid'], or $arg['nid'] not numeric supplied then return if (!is_numeric($args['nid'])) return; // get the filepath $flash['_flash'] = db_result(db_query("SELECT filepath FROM {files} WHERE filename='%s' AND nid=%d", '_flash', $args['nid'])); // retrieve parameters associated with this file from {flash} $result = db_query("SELECT height, width, version, build, display FROM {flash} WHERE nid=%d", $args['nid']); // store all the settings in to the $flash_data $result = db_fetch_object($result); foreach ($result as $parameter => $value) { $flash[$parameter] = $value; } // remove $args['nid'] from the array unset ($args['nid']); // process scaling and sizing arguments if ($args) { foreach ($args as $parameter => $value) { $xscale = $yscale = 1; switch ($parameter) { case 'scalewidth': if (is_numeric($value)) { $xscale = $yscale = $value / $flash['width']; } break; case 'scaleheight': if (is_numeric($value)) { $xscale = $yscale = $value / $flash['height']; } break; case 'xscale': if (is_numeric($value)) { $xscale = $value; } break; case 'yscale': if (is_numeric($value)) { $yscale = $value; } break; case 'scale': if (is_numeric($value)) { $xscale = $yscale = $value; } break; case 'height': case 'width': if (is_numeric($value)) { $flash[$parameter] = round($value); } break; case 'class': $flash['class'] = $value; break; default: $options[] = $parameter.':"'.$value.'"'; } $flash['width'] = round($flash['width'] * $xscale); $flash['height'] = round($flash['height'] * $yscale); } } return flash_display($flash, $options) ; } /** * Return all flash macros as an array for passing to flash_content */ function flash_get_macros($text) { $m = array(); preg_match_all('/ \[ ([^\[\]]+)* \] /x', $text, $matches); $tag_match = (array) array_unique($matches[1]); // Don't process duplicates. foreach ($tag_match as $macro) { $current_macro = '['. $macro .']'; $param = array_map('trim', explode('|', $macro)); // The first macro param is assumed to be the function name. $func_name = array_shift($param); // if flash macro found, extra other settings if ($func_name == 'flash') { $vars = array(); foreach($param as $p) { $pos = strpos($p, '='); $varname = substr($p, 0, $pos); $varvalue = substr($p, $pos + 1); $vars[$varname] = $varvalue; } $m[$current_macro] = $vars; } } return $m; } /** * Implementation of hook_filter() */ function flash_filter($op, $delta = 0, $format = -1, $text = '') { switch ($op) { case 'list': return array(0 => t('Flash')); case 'description': return t('Add flash to your posts using a flash macro.'); case 'process': foreach(flash_get_macros($text) as $unexpanded_macro => $macro) { $expanded_macro = flash_content($macro); $text = str_replace($unexpanded_macro, $expanded_macro, $text); } return $text; default: return $text; } } /** * Implementation of hook_filter_tips(). */ function flash_filter_tips($delta, $format, $long = false) { return t('Flash can be added to this post.'); } /** * Settings callback */ function flash_admin_settings() { // check for folders, create if necessary _flash_check_settings(); $form['flash_updated'] = array( '#type' => 'hidden', '#value' => time(), ); // defaults for version and build $settings = array( 'version' => 6, 'build' => 0, ); // test for numeric settings and set error if not foreach ($settings as $parameter => $value) { $cur_value = variable_get('flash_'.$parameter, $value); if (!is_numeric($cur_value)) { variable_set('flash_'.$parameter, $value); form_set_error('flash_'.$parameter, t('The @parameter was invalid. The default value has been saved.', array('@parameter' => $parameter))); } } // default file path $form['paths'] = array( '#type' => 'fieldset', '#title' => t('File path'), ); $form['paths']['flash_default_path'] = array( '#type' => 'textfield', '#title' => t('Default flash path'), '#default_value' => variable_get('flash_default_path', 'flash'), '#description' => t('Subdirectory in the directory "%dir" where Flash files will be stored. Do not include a leading or trailing slash.', array('%dir' => variable_get('file_directory_path', 'files'))), ); // other settings $form['settings'] = array( '#type' => 'fieldset', '#title' => t('Settings'), ); foreach ($settings as $parameter => $value) { $form['settings']['flash_'.$parameter] = array( '#type' => 'textfield', '#title' => t('Default '.$parameter), '#default_value' => variable_get('flash_'.$parameter, $value), '#size' => 5, '#maxlength' => 5, ); } return system_settings_form($form); }