You are here

flashnode.module in Flash Node 5.6

File

flashnode.module
View source
<?php

/**
 * Implementation of hook_help
 */
function flashnode_help($section) {
  switch ($section) {
    case 'admin/settings/flashnode':
      return t('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, or you can enable the flash filter to incorporate Flash content in to other nodes.');
    case 'admin/help#flashnode':
      return t('
      <p>Flash node lets you create nodes that store a piece of <a href="!flashurl">Flash</a> 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.</p>

      <p>The module also defines a new input filter called <strong>flash</strong> that you can use. This lets you re-use Flash content in other nodes by using the format <strong>[flash|nid=&lt;nid&gt;]</strong> 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:

      <ul><li>
      <strong>width</strong> - set a specific width, in pixels
      </li><li>
      <strong>height</strong> - set a specific height, in pixels
      </li><li>
      <strong>scale</strong> - scale both width and height to a multiple of the original size
      </li><li>
      <strong>xscale</strong> - scale just the width to a multiple of the original size
      </li><li>
      <strong>yscale</strong> - scale just the height to a multiple of the original size
      </li><li>
      <strong>scalewidth</strong> - set a specific width, in pixels, and automatically adjust the height to maintain the aspect ratio
      </li><li>
      <strong>scaleheight</strong> - set a specific height, in pixels, and automatically adjust the width to maintain the aspect ratio
      </li><li>
      <strong>class</strong> - create the container div with a specific CSS class (the default class is <em>flash</em>)
      </li></ul>

      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 <strong>[flash|nid=10|scale=0.5|class=flash-left]</strong></p>

      <p>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',
    'use display options',
    'use basic options',
    'use 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)) {

    // 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('use 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('use basic options') || user_access('use display 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('use 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',
    ),
    '#access' => user_access('use basic options') || $user->uid == 1,
    '#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',
    ),
    '#access' => user_access('use basic options') || $user->uid == 1,
    '#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('use 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 <script> is not intercepted
  $node = node_prepare($node, $teaser);

  // Prepare markup of substitution content by running through node filter
  $node->flashnode['substitution'] = check_markup($node->flashnode['substitution'], $node->format, FALSE);

  // Check if PHP processing of flashvars is needed
  $node->flashnode['flashvars'] = _flashnode_php_flashvars($node->flashnode['flashvars'], $node->format);

  // Call theme function to produce the HTML string
  $flash = theme('flashnode', $node->flashnode, $teaser);

  // If we're not in body only mode add flash if a teaser was requested
  if ($node->flashnode['display'] != 2 && $node->flashnode['display'] != 3 && $teaser) {
    $node->content['body']['#value'] = $flash . $node->content['body']['#value'];
  }

  // If we're not in teaser only mode add flash if the body was requested
  if ($node->flashnode['display'] != 1 && $node->flashnode['display'] != 3 && !$teaser) {
    $node->content['body']['#value'] = $flash . $node->content['body']['#value'];
  }

  // Return the amended node
  return $node;
}

/**
 * Return the HTML string required to generate flash content, based on an array
 * of user supplied arguments.
 *
 * The substitution content is filtered according to the specified format, and
 * if no format is specified use the default. This function is called by the
 * macro filter, but may also be called directly from PHP.
 *
 * @param $args
 *   Key          Required?   Comment
 *   nid          Yes         nid of the node containing the swf to display
 *   scaleheight  No          Scale the movie height/width to get requested height
 *   scalewidth   No          Scale the movie height/width to get the requested width
 *   xscale       No          Scale movie width by the specified factor
 *   yscale       No          Scale movie height by the specified factor
 *   scale        No          Scale height and width by the specified factor
 *   height       No          Over-ride stored height with the given value
 *   width        No          Over-ride stored width with the given value
 *   class        No          Include the given class in the $flash array
 *   flashvars    No          Include the specified flashvars string in the $flash array
 *   substitution No          Over-ride stored substitution markup
 * @param $format
 *   The filter format to apply to the substitution content. If no format is given
 *   then apply the default format.
 * @return
 *   Returns the HTML mark up for inserting the flash content, or returns nothing
 *   if the specified nid is not valid
 */
function flashnode_content($args = array(), $format = FILTER_FORMAT_DEFAULT) {

  // If no $args['nid'], or $arg['nid'] not numeric supplied then return
  if (!is_numeric($args['nid'])) {
    return;
  }

  // Get the filepath from the database
  $flash['_flashnode'] = db_result(db_query("SELECT filepath FROM {files} WHERE filename='%s' AND nid=%d", '_flashnode', $args['nid']));

  // Did we find a valid flashnode entry? If not, return empty
  if (!$flash['_flashnode']) {
    return;
  }

  // Retrieve parameters associated with this file from {flashnode}
  $result = db_query("SELECT height, width, display, substitution, flashvars, base FROM {flashnode} WHERE nid=%d", $args['nid']);

  // Store all the settings in to the $flash array
  $result = db_fetch_object($result);
  foreach ($result as $parameter => $value) {
    $flash[$parameter] = $value;
  }

  /**
   * Process flashvars for PHP. To make the site flexible we can choose to let the
   * parent node use PHP format to create a dynamic flashvar. However, we might
   * want to allow other nodes to use that dynamic flash, but without letting
   * them have wider access to the PHP format. So we process flashvars against
   * the input format of the *parent* node, not this node. If the parent allows
   * PHP then the flashvars will be processed via the PHP filter. If the user
   * supplies new flashvars via the macro format then we process again later,
   * but this time against the format of the node where the macro is running.
   * This is so that the user doesn't get access to the PHP format via the macro!
   */

  // Get parent format, accounting for the fact a revision might be in use
  $parent_format = db_result(db_query('SELECT r.format FROM {node_revisions} r INNER JOIN {node} n ON n.vid = r.vid WHERE n.nid=%d', $args['nid']));

  // Call the _flashnode_php_flashvars function to do the work
  $flash['flashvars'] = _flashnode_php_flashvars($flash['flashvars'], $parent_format);

  // Remove $args['nid'] from the array
  unset($args['nid']);

  // Initialise scaling
  $xscale = $yscale = 1;

  // Initialise options array
  $options = array();

  // Process the arguments array to modify the flash before rendering it
  if ($args) {
    foreach ($args as $parameter => $value) {
      switch ($parameter) {

        // Adjust to given width, maintaining aspect ratio
        case 'scalewidth':
          if (is_numeric($value) && $flash['width'] > 0) {
            $xscale = $yscale = $value / $flash['width'];
          }
          break;

        // Adjust to given height, maintaining aspect ratio
        case 'scaleheight':
          if (is_numeric($value) && $flash['height'] > 0) {
            $xscale = $yscale = $value / $flash['height'];
          }
          break;

        // Scale width by given factor
        case 'xscale':
          if (is_numeric($value)) {
            $xscale = $value;
          }
          break;

        // Scale height by given factor
        case 'yscale':
          if (is_numeric($value)) {
            $yscale = $value;
          }
          break;

        // Scale both width and height by given factor
        case 'scale':
          if (is_numeric($value)) {
            $xscale = $yscale = $value;
          }
          break;

        // Set height or width to specific value
        case 'height':
        case 'width':
          if (is_numeric($value)) {
            $flash[$parameter] = $value;
          }
          break;

        // Add class to $flash array (this is from flashnode 5.1)
        // This will need updating when SWFTools is finalised.
        // May no longer be supported / relevant
        case 'class':
          $flash['class'] = $value;
          break;

        // Over-ride stored flashvars with alternatives
        case 'flashvars':

          // If flashvars was set by the macro this over-rides the stored values
          // this is to allow flash to be re-used. If & has been replaced by &amp;
          // by another filter then we need to reverse that first
          $value = str_replace('&amp;', '&', $value);
          $flash['flashvars'] = $value;

          // Process for PHP content
          $flash['flashvars'] = _flashnode_php_flashvars($flash['flashvars'], $format);
          break;

        // Over-ride stored substitution text with alternatives
        // Can use !default to retrieve default content
        case 'substitution':
          $flash['substitution'] = $value;
          break;

        // If none of the above, add the parameter and value to $options array
        default:
          $options[$parameter] = $value;
      }
    }
  }
  $flash['height'] = $flash['height'] * $yscale;
  $flash['width'] = $flash['width'] * $xscale;

  // Process substitution content through filters for this node
  $flash['substitution'] = check_markup($flash['substitution'], $format, FALSE);

  // Return markup
  return theme('flashnode', $flash, FALSE, $options);
}

/**
 * Process a macro string in to an array of keys and values. Pass the array to
 * flashnode_content for processing and rendering in to an HTML string
 */
function flashnode_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 == 'flashnode') {
      $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 flashnode_filter($op, $delta = 0, $format = -1, $text = '') {
  switch ($op) {
    case 'list':
      return array(
        0 => t('Flash node filter'),
      );
    case 'description':
      return t('Add Flash from a flash node to your posts using a flash node macro.');
    case 'process':
      foreach (flashnode_get_macros($text) as $unexpanded_macro => $macro) {
        $expanded_macro = flashnode_content($macro, $format);
        $text = str_replace($unexpanded_macro, $expanded_macro, $text);
      }
      return $text;
    default:
      return $text;
  }
}

/**
 * Implementation of hook_filter_tips().
 */
function flashnode_filter_tips($delta, $format, $long = false) {
  return t('Flash node macros can be added to this post.');
}

/**
 * Settings callback
 */
function flashnode_admin_settings() {

  // Check for folders, create if necessary
  _flashnode_check_settings();

  //Reset the cache to ensure any pages using filters are updated

  // Necessary to ensure macro content regenerated in case the user modifies max_height or max_width settings
  cache_clear_all('*', 'cache_filter', true);
  $form['flashnode_updated'] = array(
    '#type' => 'hidden',
    '#value' => time(),
  );
  $form['flashnode_default_path'] = array(
    '#type' => 'textfield',
    '#title' => t('Default flash path'),
    '#default_value' => variable_get('flashnode_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'),
    )),
  );
  $form['flashnode_allowable_types'] = array(
    '#type' => 'textfield',
    '#title' => t('Allowable file types'),
    '#default_value' => variable_get('flashnode_allowable_types', 'swf flv mp3'),
    '#description' => t('You can limit the types of file that users are able to upload by entering a list of allowable file extensions separated by spaces. Do not include the leading dot.'),
  );
  $form['flashnode_default_display'] = array(
    '#type' => 'radios',
    '#title' => t('Default display setting'),
    '#default_value' => variable_get('flashnode_default_display', 0),
    '#description' => t('The default display setting that will be used when a new flash node is created.'),
    '#options' => array(
      0 => t('Teaser and body'),
      1 => t('Teaser only'),
      2 => t('Body only'),
      3 => t('Do not display'),
    ),
  );
  $form['flashnode_default_html_alt'] = array(
    '#type' => 'textarea',
    '#rows' => 5,
    '#title' => t('Default substitution content'),
    '#default_value' => variable_get('flashnode_default_html_alt', 'You are missing some Flash content that should appear here! Perhaps your browser cannot display it, or maybe it did not initialise correctly.'),
    '#description' => t('If you are using a javascript method 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. Use this content in a node by entering %default in the substitution field when creating a flash node. Note that this content is NOT filtered when it is displayed in a node so you may use mark-up that would not otherwise be allowed.', array(
      '%default' => '!default',
    )),
  );
  $form['flashnode_default_base'] = array(
    '#type' => 'textfield',
    '#title' => t('Default base parameter'),
    '#default_value' => variable_get('flashnode_default_base', base_path() . file_directory_path()),
    '#description' => t('If you use the ActionScript command %loadmovie or similar then you may need to use this setting to tell the Flash player where to find supporting movies. The base path is used for any relative paths that occur in the movie file. If you upload files using Drupal\'s upload module then the default setting of %base should be used. Only change it if you are uploading files to a different directory using something like FTP. This setting can be over-ridden when a node is created.', array(
      '%loadmovie' => 'loadMovie()',
      '%base' => base_path() . file_directory_path(),
    )),
  );
  $form['flashnode_max_width'] = array(
    '#type' => 'textfield',
    '#title' => t('Maximum displayed width'),
    '#default_value' => variable_get('flashnode_max_width', 0),
    '#description' => t('The maximum displayed width of a flash movie can be limited by entering a non-zero value here. If the movie width is greater than this width then the movie will be scaled down when it is displayed. A value of zero means that no scaling will occur. This setting can be useful to ensure that the page layout is not disrupted by a large flash movie.'),
  );
  $form['flashnode_max_height'] = array(
    '#type' => 'textfield',
    '#title' => t('Maximum displayed height'),
    '#default_value' => variable_get('flashnode_max_height', 0),
    '#description' => t('The maximum displayed height of a flash movie can be limited by entering a non-zero value here. If the movie height is greater than this height then the movie will be scaled down when it is displayed. A value of zero means that no scaling will occur. This setting can be useful to ensure that the page layout is not disrupted by a large flash movie.'),
  );
  return system_settings_form($form);
}

/**
 * Validate flashnode_admin_settings to ensure that flashnode_max_width and flashnode_max_height are valid
 */
function flashnode_admin_settings_validate($form_id, $form_values) {

  // Check max width - must be numeric and not negative
  if (!is_numeric($form_values['flashnode_max_width']) || $form_values['flashnode_max_width'] < 0) {
    form_set_error('flashnode_max_width', t('The maximum displayed width must be zero or a positive number.'));
  }

  // Check max height - must be numeric and not negative
  if (!is_numeric($form_values['flashnode_max_height']) || $form_values['flashnode_max_height'] < 0) {
    form_set_error('flashnode_max_height', t('The maximum displayed height must be zero or a positive number.'));
  }
}

/**
 * Verify that the flash folders exist and create them if they don't
 */
function _flashnode_check_settings() {

  // Build the two relevant paths
  $flashnode_path = file_create_path(variable_get('flashnode_default_path', 'flash'));
  $temp_path = $flashnode_path . '/temp';

  // Check they exist, create if not
  file_check_directory($flashnode_path, FILE_CREATE_DIRECTORY, 'flashnode_default_path');
  file_check_directory($temp_path, FILE_CREATE_DIRECTORY, 'flashnode_default_path');
}

/**
 * Create a flash filename in the flash folder, or in the temporary flash folder
 */
function _flashnode_filename($filename, $temp = FALSE) {

  // Spaces can cause problems, so replace them with underscores
  $filename = str_replace(' ', '_', $filename);

  // Get the flash path
  $result = variable_get('flashnode_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;
}

/**
 * Move a temporary file to the flash directory and store information in {files}
 */
function _flashnode_insert($nid, $flash, $mime) {

  // Create the destination path and filename from the current name
  $dest = _flashnode_filename(basename($flash));

  // Try to move the flash file to the flash folder, auto renames if it already exists
  if (file_move($flash, $dest)) {

    // Add file data to $node->file
    $file->filename = '_flashnode';
    $file->filepath = _flashnode_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;
  }
}

/**
 * Implementation of hook_after_build to perform some form processing
 *
 * 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 identifier in case the title
 * is being translated. Not sure if this is the right way to achieve this, but
 * it appears to work!
 *
 * This function is also used to set the substitution text to !default when the
 * form is first opened, but to then allow the user to submit blanks if they
 * don't want any substitution to appear. If you just use
 * $node->flashnode['substitution'] ? $node->flashnode['substitution'] : '!default'
 * then a blank substitution is treated as an undefined node and !default gets
 * put in, when the blank is in fact a valid value.
 */
function _flashnode_form_after_build($form, $form_values) {

  // Change file upload description to reflect current upload if there is one
  if (!empty($form_values['flashnode']['_flashnode']) && $form['#parents'][0] == 'flashfile') {
    $form['#description'] = t('Current file is %filename. Click "Browse..." to upload a different file.', array(
      '%filename' => basename($form_values['flashnode']['_flashnode']),
    ));
  }

  // If width field is empty then reset it to the default width
  if (empty($form_values['flashnode']['width']) && $form['#parents'][1] == 'width') {
    $form['#value'] = $form_values['flashnode']['_width'];
    form_set_value($form, $form_values['flashnode']['_width']);
  }

  // If height field is empty then reset it to the default height
  if (empty($form_values['flashnode']['height']) && $form['#parents'][1] == 'height') {
    $form['#value'] = $form_values['flashnode']['_height'];
    form_set_value($form, $form_values['flashnode']['_height']);
  }

  // If there is no flash file name, set substitution text to !default as this is a new form, provided there
  // isn't currently anything in the substitution area (in case user made an error and only partially completed
  // the form) We do it this way so that the user can have a blank without that being over-ridden by !default
  if (empty($form_values['flashnode']['_flashnode']) && $form['#parents'][1] == 'substitution' && empty($form_values['flashnode']['substitution'])) {
    $form['#value'] = '!default';
    form_set_value($form, '!default');
  }

  // Return the amended form element
  return $form;
}

/**
 * Check to see if PHP is allowed in this format, and if it is process the flashvars
 * string through the PHP filter in case there is some code to be handled. Then
 * the string for safe handling, but turn &amp; back in to & as that is what
 * flash needs to define the variables in a flashvars string. Return the result.
 */
function _flashnode_php_flashvars($flashvars, $format = -1) {

  // Get the list of filters for this node
  $filters = filter_list_format($format);

  // Look for module == filter and delta == 1
  // If found that means we have PHP allowed for this node so process it
  foreach ($filters as $filter) {
    if ($filter->module == 'filter' && $filter->delta == 1) {
      $flashvars = module_invoke($filter->module, 'filter', 'process', $filter->delta, $format, $flashvars);
    }
  }

  // Encode flashvars to make it safe for inclusion on the page
  $flashvars = check_plain($flashvars);

  // But we need to undo conversion of & to &amp;
  $flashvars = str_replace('&amp;', '&', $flashvars);
  return $flashvars;
}

/**
 * Create the HTML for insertion of Flash using SWFTools to do the work if available
 *
 * @param $flashnode
 *   A structured array that defines an item of Flash content. Must include
 *   keys filepath (path to the file), width, height, substitution (string containing
 *   HTML mark up for the substitution content), and optionally flashvars. Other keys
 *   may be included and they will be passed through to SWFTools.
 *   Key          Comment
 *   filepath     path to an swf file to theme
 *   width        display width of the swf file
 *   height       display height of the movie
 *   substitution substitution content to use if using JavaScript insertion
 *   flashvars    flashvars string to pass to the swf file
 *   base         base parameter to pass to the swf file
 * @param $teaser
 *   Flag to indicate whether teaser content is being generated. Not used by flash node
 *   but could be used by other themers to provide different output depending on mode
 * @param $options
 *   Optional array of other parameters that will passed through to swf tools theme function
 * @return
 *   An HTML string for rendering the flash content
 */
function theme_flashnode($flashnode, $teaser = FALSE, $options = array()) {

  // Modify height and width to comply with limits, if required
  $max_width = variable_get('flashnode_max_width', 0);
  $max_height = variable_get('flashnode_max_height', 0);

  // Check width first
  if ($max_width) {
    if ($flashnode['width'] > $max_width) {
      $scale = $max_width / $flashnode['width'];
      $flashnode['width'] = $flashnode['width'] * $scale;
      $flashnode['height'] = $flashnode['height'] * $scale;
    }
  }

  // Then check height
  if ($max_height) {
    if ($flashnode['height'] > $max_height) {
      $scale = $max_height / $flashnode['height'];
      $flashnode['width'] = $flashnode['width'] * $scale;
      $flashnode['height'] = $flashnode['height'] * $scale;
    }
  }

  // Generate output
  $output .= theme('flashnode_markup', $flashnode, $options);

  // Return the HTML
  return $output;
}

/**
 * Generate fallback HTML if the SWF Tools module is not available
 *
 * Flash node uses SWF Tools to handle JavaScript replacement but this isn't
 * always easy to set up. To assist users Flash node will fall back to direct
 * HTML embedding if it can't find SWF Tools. This means Flash node will work
 * 'out of the box' in a basic fashion, and is extended when SWF Tools is available
 * rather than being entirely dependent upon it.
 *
 * This function is called with an array of parameters that define a flashnode. See
 * the description theme_flashnode for details.
 */
function theme_flashnode_markup($flashnode, $options = array()) {

  // Generate HTML markup, using SWFTools if available, fallback if not
  if (function_exists('swf')) {

    // Add width, height and base to $params for SWFTools, rounding width and height to integers
    $params = array(
      'width' => round($flashnode['width']),
      'height' => round($flashnode['height']),
      'base' => $flashnode['base'],
    );

    // Retrieve default substitution content if required
    // Note we are bypassing the filters here, so we assume the administrator
    // created valid mark-up that everyone else can use!
    $preview = t($flashnode['substitution'], array(
      '!default' => variable_get('flashnode_default_html_alt', 'You are missing some Flash content that should appear here! Perhaps your browser cannot display it, or maybe it did not initialise correctly.'),
    ));
    $options = array_merge($options, array(
      'html_alt' => $preview,
    ));
    $file = $flashnode['_flashnode'];

    // If using public download then encoding spaces that the upload module may have allowed
    // Private downloads will do this for us
    if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC) {
      $file = str_replace(' ', '%20', $file);
    }

    // Get HTML from SWF Tools
    $output .= swf(file_create_url($file), $params, $flashnode['flashvars'], $options, SWFDEFAULT, 0);

    // Return result
    return $output;
  }

  // Initialise variable to ensure we only show error once if trying to render mp3 or flv with basic embedding
  static $markup_error_shown = false;

  // If file type is flv or mp3 we can't show it without SWF Tools
  if (preg_match('@flv|mp3$@i', $flashnode['_flashnode'])) {
    if (!$markup_error_shown) {
      drupal_set_message(t('Flash node needs !swftools in order to play mp3 or flv files.', array(
        '!swftools' => l('SWF Tools', 'http://drupal.org/project/swftools'),
      )), 'warning');
      $markup_error_shown = true;
    }
    return;
  }

  // Use t() to substitute parameters in to basic Flash markup
  $output = t('<div class="flashnode"><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="!width" height="!height" id="myMovieName"><param name="allowScriptAccess" value="sameDomain" /><param name="allowFullScreen" value="true" /><param name="movie" value="!filepath" /><param name="quality" value="high" /><param name="flashvars" value="!flashvars" /><param name="base" value="!base" /><embed src="!filepath" allowScriptAccess="sameDomain" allowFullScreen="true" quality="high" width="!width" height="!height" flashvars="!flashvars" name="myMovieName" align="" type="application/x-shockwave-flash" base="!base" pluginspage="http://www.macromedia.com/go/getflashplayer" /></object></div>', array(
    '!height' => $flashnode['height'],
    '!width' => $flashnode['width'],
    '!filepath' => file_create_url($flashnode['_flashnode']),
    '!flashvars' => $flashnode['flashvars'],
    '!base' => $flashnode['base'],
  ));
  return $output;
}

/**
 * Generate Flash import form
 * The returned form varies depending on the state. It presents either a list of files
 * available for import, or a confirmation form if some files have been selected for import
 */
function flashnode_import() {

  // If form was submitted and some files were checked, then return confirmation form
  if ($_POST['op'] == t('Import') && $_POST['files']) {
    return drupal_get_form('flashnode_import_confirm');
  }

  // Otherwise retrieve the form showing a list of available files to import
  $output .= drupal_get_form('flashnode_import_form');
  return $output;
}

/**
 * Form definition function to show list of files available for import
 */
function flashnode_import_form() {
  $form['help'] = array(
    '#value' => t('
      <p>This feature can be used to import files directly and create Flash nodes from them. This can be useful for importing batches of files that have been uploaded to the server, or to import files that are too large to be uploaded via the node creation form. Note that files that are imported do not respect file size limitations that would apply to files uploaded via the node form. Nodes that are created by this import function are set to be unpublished.</p>
      <p>The import function will scan the %directory directory and sub-directories to locate files for import.</p>', array(
      '%directory' => base_path() . file_create_path(variable_get('flashnode_default_path', 'flash')),
    )),
  );

  // Get the list of files that aren't in the database
  $filesnotindb = _flashnode_filesnotindb();

  // Output count of files not in the database
  if ($filesnotindb) {
    $form['count'] = array(
      '#value' => format_plural(count($filesnotindb), '1 file found.', '@count files found.') . t(' Select the file(s) you want to import, then click \'Import\'.'),
    );
  }
  else {
    $form['count'] = array(
      '#value' => t('No files were found for import.'),
    );
  }

  // Process each result in turn and build check box list
  $files = array();
  foreach ($filesnotindb as $file) {
    $files[$file] = '';

    // Can't use file_create_url as the links fail if the site uses private transfers so force a public url instead
    $form['file'][$file] = array(
      '#value' => l(str_replace(file_create_path(variable_get('flashnode_default_path', 'flash')) . '/', '', $file), $GLOBALS['base_url'] . '/' . $file),
    );
  }

  // Add list of files to checkboxes
  $form['files'] = array(
    '#type' => 'checkboxes',
    '#options' => $files,
  );

  // Action button
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Import'),
  );
  return $form;
}

/**
 * Return an array of files that are not currently in the {files} table
 */
function _flashnode_filesnotindb() {

  // Prepare array to hold results
  $filesnotindb = array();

  // Get all the files out the {files} table and store as qualified path
  $result = db_query('SELECT filepath FROM {files} ORDER BY filepath ASC');
  $filesindb = array();
  while ($file = db_fetch_object($result)) {
    $filesindb[] = file_create_path($file->filepath);
  }

  // Get all the files out of the directory structure
  $filesonserver = _flashnode_directorytoarray(realpath(file_create_path(variable_get('flashnode_default_path', 'flash'))), TRUE);

  // Sort the rows to make it easier to compare to file listing in FTP
  asort($filesonserver);

  // Get the root path - will need this later
  $root = realpath('.');

  // Process each result in turn
  foreach ($filesonserver as $file) {

    // Strip out the root path to leave just a drupal path
    $file = preg_replace('@' . preg_quote($root) . '.@', '', $file);

    // Correct for Windows using \ in place of /
    $file = str_replace("\\", "/", $file);

    // Check it isn't a directory - not interested
    if (!file_check_directory($file)) {

      // Check to see if file is NOT in the database
      if (!in_array($file, $filesindb)) {

        // If we get here we have a file that isn't in the database
        $filesnotindb[] = $file;
      }
    }
  }
  return $filesnotindb;
}

/**
 * Helper function - recurse directories and files in to an array
 * http://snippets.dzone.com/posts/show/155
 */
function _flashnode_directorytoarray($directory, $recursive) {
  $array_items = array();
  if ($handle = opendir($directory)) {
    while (false !== ($file = readdir($handle))) {
      if ($file != "." && $file != "..") {
        if (is_dir($directory . "/" . $file) && $file != 'temp') {
          if ($recursive) {
            $array_items = array_merge($array_items, _flashnode_directorytoarray($directory . "/" . $file, $recursive));
          }
          $file = $directory . "/" . $file;
          $array_items[] = preg_replace("/\\/\\//si", "/", $file);
        }
        else {
          $file = $directory . "/" . $file;
          $array_items[] = preg_replace("/\\/\\//si", "/", $file);
        }
      }
    }
    closedir($handle);
  }
  return $array_items;
}

/**
 * Theme flashnode_import_form
 */
function theme_flashnode_import_form($form) {

  // Render help message
  $output .= drupal_render($form['help']);

  // Render count
  $output .= drupal_render($form['count']);

  // If there are files found
  if (isset($form['file']) && is_array($form['file'])) {

    // Construct table of files
    $header = array(
      theme('table_select_header_cell'),
      t('File'),
    );
    foreach (element_children($form['file']) as $key) {
      $row = array();
      $row[] = drupal_render($form['files'][$key]);
      $row[] = drupal_render($form['file'][$key]);
      $rows[] = $row;
    }

    // Render themed table
    $output .= theme('table', $header, $rows);

    // Render action
    $output .= drupal_render($form['submit']);
  }

  // Return output
  return $output;
}

/**
 * Confirmation form for user to confirm import of selected items
 */
function flashnode_import_confirm() {
  $edit = $_POST;
  $form['files'] = array(
    '#prefix' => '<ul>',
    '#suffix' => '</ul>',
    '#tree' => TRUE,
  );

  // array_filter in the call returned only elements with TRUE values
  foreach (array_filter($edit['files']) as $file) {
    $form['files'][$file] = array(
      '#type' => 'hidden',
      '#value' => $file,
      '#prefix' => '<li>',
      '#suffix' => check_plain(str_replace(file_create_path(variable_get('flashnode_default_path', 'flash')) . '/', '', $file)) . "</li>\n",
    );
  }
  $form['operation'] = array(
    '#type' => 'hidden',
    '#value' => 'import',
  );
  return confirm_form($form, t('Are you sure you want to import these items?'), 'admin/content/flashnode', '', t('Import'), t('Cancel'));
}

/**
 * Submit handler for import confirmation
 * This function does the actual import of each selected file
 */
function flashnode_import_confirm_submit($form_id, $form_values) {
  if ($form_values['confirm']) {
    foreach ($form_values['files'] as $file) {
      flashnode_import_file($file);
    }
  }
  return 'admin/content/node';
}

/**
 * Import function called by flashnode_import_confirm_submit
 * It is called once for each file that is to be imported
 * $file_to_import is a Drupal path to a file for import
 */
function flashnode_import_file($file_to_import) {

  // Need to access the user object
  global $user;

  // Initialise a node and file object
  $node = new stdClass();
  $file = new stdClass();

  // Populate basic data in to the node
  $node->title = check_plain(basename($file_to_import));
  $node->uid = $user->uid;
  $node->type = 'flashnode';
  $node->status = 0;

  // Try to get the file settings for this file, using image_get_info
  $info = image_get_info(realpath($file_to_import));
  $node->flashnode['height'] = $info['height'];
  $node->flashnode['width'] = $info['width'];
  $file->filemime = $info['mime_type'];

  // Set other flash node defaults
  $node->flashnode['display'] = variable_get('flashnode_default_display', 0);
  $node->flashnode['substitution'] = '!default';
  $node->flashnode['base'] = variable_get('flashnode_default_base', base_path() . file_directory_path());

  // Set a flag to tell flashnode_insert we are adding files via import
  $node->flashnode['import'] = TRUE;

  // Prepare the file object
  $file->filename = basename($file_to_import);
  $file->filepath = str_replace(file_create_path() . '/', '', $file_to_import);
  $file->filesize = filesize(realpath($file_to_import));

  // If we didn't get mime type from earlier attempt we will need to try and guess it from the extension
  if (!$file->filemime) {
    if (preg_match('@swf|flv|mp3$@i', $file->filename, $matches)) {
      switch (strtolower($matches[0])) {
        case 'mp3':
          $file->filemime = 'audio/mpeg';
          break;
        case 'flv':
        default:
          $file->filemime = 'application/octet-stream';
      }
    }
  }

  // Save the node
  node_save($node);

  // Add file to the 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, $node->nid, '_flashnode', $file->filepath, $file->filemime, $file->filesize);

  // Insert data in the flash table now we have the file number and the nid
  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);

  // Show a status message
  // If successful, show message and write an entry to the watchdog
  // If unsuccessful only show on the screen
  // Reduce $file_to_import to simple name
  $file_to_import = str_replace(file_create_path(variable_get('flashnode_default_path', 'flash')) . '/', '', $file_to_import);

  // Show appropriate message - $node->nid only exists if node_save succeeded
  if ($node->nid) {
    drupal_set_message('Imported ' . $file_to_import);
    watchdog('content', t('@type: imported %title.', array(
      '@type' => t($node->type),
      '%title' => $node->title,
    )), WATCHDOG_NOTICE, l(t('view'), "node/{$node->nid}"));
  }
  else {
    drupal_set_message('Failed to import ' . $file_to_import, 'warning');
  }
  return;
}

/**
 * Implementation of hook_file_download
 * To allow flash node to work with a private file system
 */
function flashnode_file_download($file) {

  // See if this file belongs to flash node by querying database
  $result = db_query("SELECT fi.*, fl.nid FROM {files} fi INNER JOIN {flashnode} fl ON fi.fid = fl.fid WHERE filepath = '%s'", $file);

  // See if we got a result
  if ($file = db_fetch_object($result)) {

    // Check if the user is allowed to view this node, and if they are, return headers, else return access denied
    $node = node_load($file->nid);
    if (node_access('view', $node)) {
      return array(
        'Content-Type: ' . $file->filemime,
        'Content-Length: ' . $file->filesize,
      );
    }
    else {
      return -1;
    }
  }
}

/**
 * Load views support if necessary
 */
if (module_exists('views')) {
  include drupal_get_path('module', 'flashnode') . '/flashnode.views.inc';
}

Functions

Namesort descending Description
flashnode_access Implementation of hook_access
flashnode_admin_settings Settings callback
flashnode_admin_settings_validate Validate flashnode_admin_settings to ensure that flashnode_max_width and flashnode_max_height are valid
flashnode_content Return the HTML string required to generate flash content, based on an array of user supplied arguments.
flashnode_cron Implements hook_cron (delete old temp files)
flashnode_delete Implementation of hook_delete.
flashnode_file_download Implementation of hook_file_download To allow flash node to work with a private file system
flashnode_filter Implementation of hook_filter()
flashnode_filter_tips Implementation of hook_filter_tips().
flashnode_form Implementation of hook_form
flashnode_get_macros Process a macro string in to an array of keys and values. Pass the array to flashnode_content for processing and rendering in to an HTML string
flashnode_help Implementation of hook_help
flashnode_import Generate Flash import form The returned form varies depending on the state. It presents either a list of files available for import, or a confirmation form if some files have been selected for import
flashnode_import_confirm Confirmation form for user to confirm import of selected items
flashnode_import_confirm_submit Submit handler for import confirmation This function does the actual import of each selected file
flashnode_import_file Import function called by flashnode_import_confirm_submit It is called once for each file that is to be imported $file_to_import is a Drupal path to a file for import
flashnode_import_form Form definition function to show list of files available for import
flashnode_insert Implementation of hook_insert
flashnode_load Implementation of hook_load
flashnode_menu Implementation of hook_menu
flashnode_node_info Implementation of hook_node_info
flashnode_perm Implementation of hook_perm
flashnode_prepare Implementation of hook_prepare().
flashnode_update Implementation of hook_update
flashnode_validate Implementation of hook_validate
flashnode_view Implementation of hook_view
theme_flashnode Create the HTML for insertion of Flash using SWFTools to do the work if available
theme_flashnode_import_form Theme flashnode_import_form
theme_flashnode_markup Generate fallback HTML if the SWF Tools module is not available
_flashnode_check_settings Verify that the flash folders exist and create them if they don't
_flashnode_directorytoarray Helper function - recurse directories and files in to an array http://snippets.dzone.com/posts/show/155
_flashnode_filename Create a flash filename in the flash folder, or in the temporary flash folder
_flashnode_filesnotindb Return an array of files that are not currently in the {files} table
_flashnode_form_after_build Implementation of hook_after_build to perform some form processing
_flashnode_insert Move a temporary file to the flash directory and store information in {files}
_flashnode_php_flashvars Check to see if PHP is allowed in this format, and if it is process the flashvars string through the PHP filter in case there is some code to be handled. Then the string for safe handling, but turn &amp; back in to & as that is what flash…