<?php
// $Id: emfield.module,v 1.12.4.48 2010/10/03 21:53:00 aaron Exp $

/**
 * @file
 *   Embedded Media Field is a CCK-based framework for 3rd party media files.
 */

/**
 * Implementation of hook_menu().
 */
function emfield_menu() {
  $items['admin/content/emfield'] = array(
    'file' => 'emfield.admin.inc',
    'title' => 'Embedded Media Field configuration',
    'description' => 'Configure Embedded Media Field: Allow content types to use various 3rd party providers, enter API keys, etc.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('emfield_settings'),
    'access arguments' => array('administer site configuration'),
  );
  $items['admin/content/emfield/media'] = array(
    'file' => 'emfield.admin.inc',
    'title' => 'Media settings',
    'description' => 'Configure Embedded Media Field: Allow content types to use various 3rd party providers, enter API keys, etc.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('emfield_settings'),
    'access arguments' => array('administer site configuration'),
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );

  if (module_exists('job_queue')) {
    $items['admin/content/emfield/reload'] = array(
      'file' => 'emfield.admin.inc',
      'title' => 'Reload data',
      'description' => 'Reload emfield fields in bulk',
      'page callback' => 'drupal_get_form',
      'page arguments' => array('emfield_settings_jobqueue'),
      'access arguments' => array('administer site configuration'),
      'type' => MENU_LOCAL_TASK,
    );
  }

  return $items;
}

function emfield_field_columns($field) {
  module_load_include('inc', 'emfield', 'emfield.cck');

  return _emfield_field_columns($field);
}

/**
 *  A helper function for hook_field(), called by the various sub-modules.
 */
function emfield_emfield_field($op, &$node, $field, &$items, $teaser, $page, $module) {
  module_load_include('inc', 'emfield', 'emfield.cck');
  return _emfield_emfield_field($op, $node, $field, $items, $teaser, $page, $module);
}

/**
 *  Helper function to implement hook_content_is_empty.
 */
function emfield_emfield_content_is_empty($item, $field) {
  return empty($item['value']);
}

/**
 * Return a list of providers allowed for a specific field.
 */
function emfield_allowed_providers($field, $module) {
  $allowed_providers = emfield_system_list($module);

  // $field sometimes is the whole $field and sometimes just the $widget,
  // depending on where it is called from, so check which one we have.
  $providers = isset($field['widget']['providers']) ? $field['widget']['providers'] : (isset($field['providers']) ? $field['providers'] : array());
  $allow_all = TRUE;
  foreach ($allowed_providers as $test) {
    if (!variable_get('emfield_'. $module .'_allow_'. $test->name, TRUE)) {
      unset($allowed_providers[$test->name]);
    }
    else {
      $allow_all &= empty($providers[$test->name]);
    }
  }
  if (!$allow_all) {
    foreach ($allowed_providers as $test) {
      if (empty($providers[$test->name])) {
        unset($allowed_providers[$test->name]);
      }
    }
  }
  return $allowed_providers;
}

/**
 *  This returns a list of content types that are implemented by emfield.
 */
function emfield_implement_types($cached = TRUE) {
  static $types;

  if (!isset($types) || !$cached) {
    // If it's a cachable request, try to load a cached value.
    if ($cached && $cache = cache_get('emfield_implement_types', 'cache')) {
      $types = $cache->data;
    }
    else {
      $system_types = _content_type_info();
      $content_types = $system_types['content types'];
      $field_types = $system_types['field types'];

      // The array that will store type/field information for provider import.
      $types = array();
      $modules = array();

      foreach (module_implements('emfield_info', TRUE) as $module) {
        $modules[$module] = $module;
      }

      // Settings per content type for the module.
      foreach ($content_types as $content_type => $type) {
        // Determine which content types implement this module.
        foreach ($type['fields'] as $field_type => $field) {

          // If this field type is defined by this module, then include it here.
          if (!empty($modules[$field_types[$field['type']]['module']])) {
            // Settings per content type per module.
			$module = $modules[$field_types[$field['type']]['module']];
            $types[$module][$content_type][$field_type] = $field;
          }
        }
      }
    }
  }

  cache_set('emfield_implement_types', $types, 'cache', CACHE_PERMANENT);

  return $types;
}

/**
 * This will parse the url or embedded code pasted by the node submitter.
 *
 * @return
 *   Either an empty array (if no match), or an array of 'provider' and 'value'.
 */
function emfield_parse_embed($field, $embed = '', $module) {
  $providers = emfield_allowed_providers($field, $module);
  foreach ($providers as $provider) {
    $success = emfield_include_invoke($module, $provider->name, 'extract', trim($embed), $field);

    // We've been given an array of regex strings, so try to find a match.
    if (is_array($success)) {
      foreach ($success as $regex) {
        $matches = NULL;
        if (preg_match($regex, trim($embed), $matches)) {
          return array('provider' => $provider->name, 'value' => $matches[1]);
        }
      }
    }
    // the invoked include module did its own parsing and found a match
    else if ($success) {
      return array('provider' => $provider->name, 'value' => $success);
    }
  }

  // We found no match.
  return array();
}

/**
 *  Extract the id from embedded code or url.
 */
function _emfield_field_validate_id($field, $item, $error_field, $module, $delta = 0) {
  // Load the provider info.
  $item = _emfield_field_submit_id($field, $item, $module, $error_field);
  // Ensure we have proper provider info.
  if ($item['embed'] && !$item['provider']) {
    form_set_error($error_field, t('You have specified an invalid media URL or embed code.'));
  }
  else {
    emfield_include_invoke($module, $item['provider'], 'validate', $item['value'], $error_field);
  }

  return $item;
}

/**
 *  Replace embedded code with the extracted id. this goes in the field 'value'.
 *  This also allows you to grab directly from the URL to display the content from field 'provider'.
 */
function _emfield_field_submit_id($field, $item, $module) {

  // @TODO Find the right fix for this.
  // When the embedded media field is used in the default value widget
  // when editing field settings, the $item has no value for 'provider',
  // causing an error message.
  // This is not the right way to fix this, but I don't know why that
  // value has been left out of the form element returned by hook_widget_settings
  // and this will at least keep the error message from being displayed.

  if (!isset($item['provider'])) {
    $item['provider'] = '';
  }
  $item = array_merge($item, emfield_parse_embed($field, $item['embed'], $module));
  $item['data'] = (array)emfield_include_invoke($module, $item['provider'], 'data', $field, $item);
  $item['version'] = intval(emfield_include_invoke($module, $item['provider'], 'data_version', $field, $item));

  return $item;
}

/**
 *  Format our field for display. This is actually called originally by each helper module
 *  that implements hook_field_formatter, which then call this.
 */
function emfield_emfield_field_formatter($field, $item, $formatter, $node, $module, $options = array()) {
  // If we're coming from a preview, we need to extract our new embedded value.
  if (isset($node->in_preview)) {
    $item = emfield_parse_embed($field, $item['embed'], $module);
  }

  // If we have no value, then return an empty string.
  if (!isset($item['value'])) {
    return '';
  }

  // Unfortunately, when we come from a view, we don't get all the widget fields.
  if (!$node->type) {
    $type = content_types($field['type_name']);
    $field['widget'] = $type['fields'][$field['field_name']]['widget'];
  }

  // Sometimes our data is still unserialized, again from views.
  if (!is_array($item['data'])) {
    $item['data'] = (array)unserialize($item['data']);
  }

  // The individual modules actually define the theme for the formatter.
  $output = '';
  $output .= theme($module .'_'. $formatter, $field, $item, $formatter, $node, $options);

  return $output;
}

/** Widgets **/
function emfield_emfield_widget_settings($op, $widget, $module) {
  module_load_include('inc', 'emfield', 'emfield.cck');
  return _emfield_emfield_widget_settings($op, $widget, $module);
}

function emfield_emfield_widget(&$form, &$form_state, $field, $items, $delta = 0, $module) {
  module_load_include('inc', 'emfield', 'emfield.cck');

  return _emfield_emfield_widget($form, $form_state, $field, $items, $delta, $module);
}

/**
 * Implementation of hook_node_operations().
 */
function emfield_node_operations() {
  $operations = array(
    'emfield_reload' => array(
      'label' => t('Reload Embedded Media Data'),
      'callback' => 'emfield_operations_reload',
    ),
  );

  return $operations;
}

/**
 *  This reloads and saves the data for all the nid's in the array.
 */
function emfield_operations_reload($nids = array(), $show_message = TRUE) {
  foreach ($nids as $nid) {
    if ($node = node_load($nid)) {
      $type = content_types($node->type);
      foreach ($type['fields'] as $field) {
        if (module_hook($field['type'], 'emfield_info')) {
          $message = "Reloaded %node-title's %field.";
          $message_variables = array('%node-title' => $node->title, '%field' => $field['type_name']);
          watchdog('emfield reload data', $message, $message_variables, WATCHDOG_NOTICE, l($node->title, 'node/'. $node->nid));
          if ($show_message) {
            drupal_set_message(t($message, $message_variables));
          }
          $items = $node->{$field['field_name']};
          emfield_emfield_field('submit', $node, $field, $items, FALSE, FALSE, $field['type']);
          $node->{$field['field_name']} = $items;
          node_save($node);
        }
      }
    }
  }
}

/**
 * Implementation of hook_nodeapi().
 */
function emfield_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
  switch ($op) {
    case 'rss item':
      module_load_include('inc', 'emfield', 'emfield.rss');
      return _emfield_nodeapi_rss($node, $op, $teaser, $page);
  }
}

/**
 * When an include file requires to read an xml to receive information, such as for thumbnails,
 * this script can be used to request the xml and return it as an array.
 * @TODO convert to simplexml
 *   @param $provider
 *     the string of the third party provider, such as 'youtube', 'flikr', or 'google'
 *   @param $url
 *     the url for the xml request
 *   @param $args
 *     an array of args to pass to the xml url
 *   @param $cached
 *     optional; if TRUE, the result of this xml request will be cached. good to play nice w/
 *     the third party folks so they don't stop providing service to your site...
 *   @param $return_errors
 *     optional; if TRUE and an error is encountered, a descriptive error array will be returned with elements for
 *     code, message and stat => 'error'
 *   @param $hash_extra
 *     optional; The key for caching is created from the arguments.  If your provider does not use arguments
 *     (or uses the same arguments for each media item, you must pass a unique string as $hash_extra.  Currently
 *     this is only used by bliptv and archive.org
 *   @param $serialized
 *     optional; Most uses of this function are expecting an XML file to be returned.  However some providers (Flickr)
 *     can instead return a serialized PHP array.  In this case set $serialized to TRUE.
 *  @param $json
 *    If TRUE, then the result will be a json encoded string.
 *   @return
 *     the xml results returned as an array
 */
function emfield_request_xml($provider, $url, $args = array(), $cached = TRUE, $return_errors = FALSE, $hash_extra = FALSE, $serialized = FALSE, $json = FALSE) {
  ksort($args);

  // Build an argument hash that we'll use for the cache id and api signing.
  $arghash = $provider .':';
  foreach ($args as $k => $v) {
    $arghash .= $k . $v;
  }

  // Build the url.
  foreach ( $args as $k => $v) {
    $encoded_params[] = urlencode($k) .'='. urlencode($v);
  }
  if (!empty($encoded_params)) {
    $url .= '?'. implode('&', $encoded_params);
  }

  // some providers, such as bliptv, actually change the url, and not just the queries.
  // we provide an extra section for a unique identifier in that case
  if (isset($hash_extra)) {
    $arghash .= ':'. $hash_extra;
  }

  // if it's a cachable request, try to load a cached value
  if ($cached && $cache = cache_get($arghash, 'cache')) {
    return $cache->data;
  }

  // connect and fetch a value
  $result = drupal_http_request($url);

  if (!empty($result->error)) {
    if ($return_errors) {
      return array(
        'stat' => 'error',
        'code' => $result->code,
        'message' => 'HTTP Error: '. $result->error,
      );
    }
    emfield_set_error(t("Could not connect to @provider, HTTP error @error", array('@error' => $result->code, '@provider' => $provider)));

    return array();
  }

  if ($json) {
    $response = (array)json_decode($result->data);
  }
  else if ($serialized) {
    // Flickr gives us a serialized php array. Make sure it unserializes.
    $response = unserialize($result->data);
    if (!$response) {
      if ($return_errors) {
        return array(
          'stat' => 'error',
          'code' => '-1',
          'message' => 'The response was corrupted, it could not be unserialized.',
        );
      }

      emfield_set_error(t("The response from @provider was corrupted and could not be unserialized.", array('@provider' => $provider)));

      return array();
    }
  }
  else {
    $parser = drupal_xml_parser_create($result->data);
    $vals = array();
    $index = array();
    xml_parse_into_struct($parser, $result->data, $vals, $index);
    xml_parser_free($parser);

    $response = array();
    $response['_emfield_arghash'] = $arghash;
    $level = array();
    $start_level = 1;
    foreach ($vals as $xml_elem) {
      if ($xml_elem['type'] == 'open') {
        if (array_key_exists('attributes', $xml_elem)) {
          list($level[$xml_elem['level']], $extra) = array_values($xml_elem['attributes']);
        }
  else {
          $level[$xml_elem['level']] = $xml_elem['tag'];
        }
      }
      if ($xml_elem['type'] == 'complete') {
        $php_stmt = '$response';
        while ($start_level < $xml_elem['level']) {
          $php_stmt .= '[$level['. $start_level .']]';
          $start_level++;
        }
        $php_stmt .= '[$xml_elem[\'tag\']][] = $xml_elem[\'value\'];'. $php_stmt .'[$xml_elem[\'tag\']][] = $xml_elem[\'attributes\'];';
        eval($php_stmt);
        $start_level--;
      }
    }
  }

  if ($cached) {
    cache_set($arghash, $response, 'cache', time() + variable_get('emfield_cache_duration', 3600));
  }

  return $response;
}

/**
 * Get the HTTP Header of media, for mime-type and length.
 *
 * @param $provider
 *   The string of the third party provider, such as 'youtube', 'flikr', or 'google'.
 * @param $url
 *   The url for the media.
 * @param $cached
 *   Optional; if TRUE, the result of this xml request will be cached. good to play nice w/
 *   the third party folks so they don't stop providing service to your site...
 * @return
 *   The header results, returned as an array.
 */
function emfield_request_header($provider, $url, $cached = TRUE, $return_errors = TRUE) {
  // if it's cacheable, try to load a cached value
  if ($cached && $cache = cache_get($url, 'cache')) {
    return $cache->data;
  }

  $result = _emfield_http_request_header($url);

  if (!empty($result->error)) {
    if ($return_errors) {
      return $result;
    }

    emfield_set_error(t("Could not connect to @provider, HTTP error @error", array('@error' => $result->code, '@provider' => $provider)));

    return array();
  }

  // @todo does this not want to be changing 'cache' to 'cache_emfield' or similar
  cache_set($url, $result, 'cache', time() + variable_get('emfield_cache_duration', 3600));

  return $result;
}

/**
 * HTTP HEAD - just request the header.
 */
function _emfield_http_request_header($url, $retry = 4) {
  $result = drupal_http_request($url, array(), 'HEAD', NULL, 0);

  switch ($result->code) {
    // the intention here is to retry if the correct information isn't available
    // so far it's just tuned for YouTube
    // it's possible/probable that Moved Temporarily will give the headers required elsewhere
    // and it maybe best to test on the content of the header
    case 200: // OK
    case 304: // Not modified - this shouldn't happen here
      break;
    case 301: // Moved permanently
    case 302: // Moved temporarily
    case 303: // See Other <-- drupal_http_request doesn't deal with this we need this for youtube
    case 307: // Moved temporarily
      $location = $result->headers['Location'];
      if ($retry > 0) {
        $result = _emfield_http_request_header($result->headers['Location'], --$retry);
        $result->redirect_code = $result->code;
      }
      $result->redirect_url = $location;

      break;
    default:
  }

  return $result;
}

function emfield_set_error($error) {
  watchdog('emfield', '!error', array('!error' => $error), WATCHDOG_WARNING);
}

/**
 * Return an array of installed .inc files and/or loads them upon request.
 * This routine is modeled after drupal_system_listing() (and also depends on it).
 * It's major difference, however, is that it loads .inc files by default.
 *
 * @param $provider
 *   Optional; name of the passed $provider to find (e.g. "youtube", "google", etc.).
 * @param $load
 *   Defaults to TRUE; whether to include matching files into memory.
 * @return
 *   An array of file objects optionally matching $provider.
 */
function emfield_system_list($module, $provider = NULL, $load = TRUE) {
  // Maintain a static list of providers.
  static $files;

  if (!isset($files)) {
    // Initialize our static variable.
    $files = array();
  }
  if (!isset($files[$module])) {
    // Initialize the file listing for the invoking module.
    $files[$module] = array();
  }

  if ((!isset($provider) && empty($files[$module])) || (isset($provider) && !isset($files[$module][$provider]))) {
    // First find any providers external to the emfield set of modules.
    $override_files = module_invoke_all('emfield_providers', $module, $provider);

    // Next get the default providers. Note this is being phased out in v2.
    $provider_files = drupal_system_listing("$provider\.inc$", drupal_get_path('module', $module) ."/providers", 'name', 0);

    // Merge the files, allowing provider overrides.
    $provider_files = array_merge($provider_files, $override_files);
    $files[$module] = array_merge($files[$module], $provider_files);

    // Sort the providers alphabetically.
    ksort($files[$module]);
  }

  if ($load) {
    if (isset($provider) && isset($files[$module][$provider])) {
      emfield_include_list($files[$module][$provider]);
    }
    else {
      foreach ($files[$module] as $key => $file) {
        emfield_include_list($file);
      }
    }
  }

  if (isset($provider)) {
    return $files[$module][$provider];
  }
  return $files[$module];
}

/**
 * Maintains a list of all loaded include files.
 *
 * @param $file
 *   Optional; a file object (from emfield_system_list()) to be included.
 * @return
 *   An array of all loaded includes (without the .inc extension).
 */
function emfield_include_list($file = NULL) {
  static $list = array();

  if ($file && $file->filename && !isset($list[$file->filename])) {
    include_once('./'. $file->filename);
    $list[$file->filename] = $file->name;
  }

  return $list;
}

/**
 * Determine whether an include implements a hook, cf. module_hook.
 *
 * @param $provider
 *   The name of the provider file (without the .inc extension), such as 'youtube' or 'google'.
 * @param $hook
 *   The name of the hook (e.g. "thumbnail", "settings", etc.).
 * @return
 *   TRUE if the provider is loaded and the hook is implemented.
 */
function emfield_include_hook($module, $provider, $hook) {
  return function_exists($module .'_'. $provider .'_'. $hook);
}

/**
 * Invoke hook in a particular include.
 *
 * @param $module
 *  the helper module
 * @param $provider
 *   The name of the provider (without the .inc extension).
 * @param $hook
 *   The name of the hook (e.g. "settings", "thumbnail", etc.).
 * @param ...
 *   Arguments to pass to the hook implementation.
 * @return
 *   The return value of the hook implementation.
 */
function emfield_include_invoke() {
  $args     = func_get_args();
  $module = array_shift($args);
  $provider  = array_shift($args);
  $hook     = array_shift($args);
  $function = $module .'_'. $provider .'_'. $hook;
  emfield_system_list($module, $provider);
  return emfield_include_hook($module, $provider, $hook) ? call_user_func_array($function, $args) : NULL;
}

/**
 * Custom filter for provider NOT NULL.
 */
function emfield_views_handler_filter_is_not_null($op, $filter, $filterinfo, &$query) {
  if ($op == 'handler') {
    $query->ensure_table($filterinfo['table']);
    if ($filter['value']) {
      $qs = "%s.%s <> '' AND %s.%s IS NOT NULL";
    }
    else {
      $qs = "%s.%s = '' OR %s.%s IS NULL";
    }
    $query->add_where($qs, $filterinfo['table'], $filterinfo['content_db_info']['columns']['provider']['column'], $filterinfo['table'], $filterinfo['content_db_info']['columns']['provider']['column']);
  }
}

/**
 * Create a list of providers.
 *  @TODO: Is this legacy? Not sure if it's called, and seems specific to emvideo.
 */
function emfield_views_handler_filter_provider_list($op) {
  $providers = array();
  foreach (emfield_system_list('emvideo') as $provider => $info) {
    $providers[$provider] = $info->name;
  }
  return $providers;
}

/**
 * Views handler for the provider list filter.
 */
function emfield_views_handler_filter_provider($op, $filter, $filterinfo, &$query) {
  if ($op == 'handler') {
    $query->ensure_table($filterinfo['table']);
    if ($filter['operator'] == 'OR') {
      foreach ($filter['value'] as $provider) {
        $items[] = "%s.%s = '$provider'";
        $where[] = $filterinfo['table'];
        $where[] = $filterinfo['content_db_info']['columns']['provider']['column'];
      }
      $qs = implode(' OR ', $items);
    }
    else {
      foreach ($filter['value'] as $provider) {
        $items[] = "%s.%s <> '$provider'";
        $where[] = $filterinfo['table'];
        $where[] = $filterinfo['content_db_info']['columns']['provider']['column'];
      }
      $qs = implode(' AND ', $items);
    }
    $query->add_where($qs, $where);
  }
}

/**
 * Handle the provider argument. This is called from a wrapper that includes the module.
 */
function _emfield_handler_arg_provider($op, &$query, $argtype, $arg = '', $module = '') {
  if ($op == 'filter') {
    $field_name = drupal_substr($argtype['type'], 10);
  }
  else {
    $field_name = drupal_substr($argtype, 10);
  }

  $field = content_fields($field_name);
  $db_info = content_database_info($field); // TODO: This hook no longer exists in D6.
  $main_column = $db_info['columns']['provider'];

  // The table name used here is the Views alias for the table, not the actual
  // table name.
  $table = 'node_data_'. $field['field_name'];

  switch ($op) {
    case 'summary':
      $query->ensure_table($table);
      $query->add_field($main_column['column'], $table);
      $query->add_groupby($table .'.'. $main_column['column']);
      return array('field' => $table .'.'. $main_column['column']);
    case 'sort':
      $query->ensure_table($table);
      $query->add_orderby($table, $main_column['column'], $argtype);
      break;
    case 'filter':
      $query->ensure_table($table);
      $where = db_escape_string($arg);
      $query->add_where($table .'.'. $main_column['column'] ." = '%s'", $where);
      break;
    case 'link':
      $provider = emfield_system_list($module,  $query->$main_column['column']);
      $info = emfield_include_invoke($module, $provider[$query]->name, 'info');
      $title = $info['name'];
      return l($title, $arg .'/'. $query->$main_column['column']);
    case 'title':
      $provider = emfield_system_list($module,  $query);
      $info = emfield_include_invoke($module, $provider[$query]->name, 'info');
      $title = $info['name'];
      return $title ? $title : check_plain($query);
  }
}

function emfield_provider_themes($module, $provider = NULL) {
  $themes = array();

  if ($provider && $subthemes = emfield_include_invoke($module, $provider, 'subtheme')) {
    $themes = $subthemes;
  }
  $providers = emfield_system_list($module);

  foreach ($providers as $provider) {
    if ($subthemes = emfield_include_invoke($module, $provider->name, 'emfield_subtheme')) {
        $themes += $subthemes;
    }
  }

  return $themes;
}

function emfield_provider_menus($module, $provider = NULL) {
  $menus = array();

  if ($provider && $submenus = emfield_include_invoke($module, $provider, 'submenu')) {
    $menus = $submenus;
  }
  $providers = emfield_system_list($module);

  foreach ($providers as $provider) {
    if ($submenus = emfield_include_invoke($module, $provider->name, 'emfield_submenu')) {
        $menus = array_merge($menus, (array) $submenus);
    }
  }

  return $menus;
}

/**
 *  Returns the URL to the registered JW Flash Media Player, if such exists.
 */
function emfield_flvmediaplayer_url($reset = FALSE) {
  static $path;

  if (is_null($path) || $reset) {
    if (module_exists('flvmediaplayer')) {
      $path = variable_get('flvmediaplayer_path', drupal_get_path('module', 'flvmediaplayer') .'/mediaplayer.swf');
    }
    else if (is_null($path = variable_get('emfield_flvmediaplayer_url', NULL)) || (!$path && $reset)) {
      global $base_path;
      $path = '';
      $files = drupal_system_listing('(^player-viral\.swf$|^player\.swf$|^mediaplayer\.swf$)', 'plugins', 'basename', 0);
      if (!empty($files)) {
        $file = array_pop($files);
        $path = $file->filename;
      }
      else {
        $files = drupal_system_listing('(^player-viral\.swf$|^player\.swf$|^mediaplayer\.swf$)', 'modules', 'basename', 0);
        if (!empty($files)) {
          $file = array_pop($files);
          $path = $file->filename;
        }
      }
      variable_set('emfield_flvmediaplayer_url', $path);
    }
  }

  return $path;
}

/**
 *  Returns the URL to the registered JW Image Rotator, if such exists.
 */
function emfield_imagerotator_url($reset = FALSE) {
  static $path;

  if (is_null($path) || $reset) {
    if (is_null($path = variable_get('emfield_imagerotator_url', NULL)) || (!$path && $reset)) {
      global $base_path;
      $path = '';
      $files = drupal_system_listing('(^imagerotator\.swf$)', 'plugins', 'basename', 0);
      if (!empty($files)) {
        $file = array_pop($files);
        $path = $file->filename;
      }
      else {
        $files = drupal_system_listing('(^imagerotator\.swf$)', 'modules', 'basename', 0);
        if (!empty($files)) {
          $file = array_pop($files);
          $path = $file->filename;
        }
      }
      variable_set('emfield_imagerotator_url', $path);
    }
  }

  return $path;
}

/**
 * Implementation of Devel module's hook_content_generate().
 */
function emfield_content_generate($node, $field) {
  $item = $urls = array();
  $module = $field['module'];
  foreach (emfield_allowed_providers($field, $module) as $provider) {
    $provider_urls = emfield_include_invoke($module, $provider->name, 'content_generate', $node, $field);
    if (is_array($provider_urls)) {
      $urls[$provider->name] = $provider_urls;
    }
  }
  if (!empty($urls)) {
    $provider = array_rand($urls);
    $item['provider'] = $provider;
    $key = array_rand($urls[$provider]);
    $item['embed'] = $urls[$provider][$key];
    $item = _emfield_field_submit_id($field, $item, $module);
  }
  return $item;
}

/**
 *  Helper function for hook_field_settings().
 */
function emfield_emfield_field_settings($op, $field) {
  module_load_include('inc', 'emfield', 'emfield.cck');
  return _emfield_emfield_field_settings($op, $field);
}

/**
 * Implementation of hook_views_api().
 */
function emfield_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'emfield') . '/includes/views',
  );
}

/**
 * Implementation of hook_theme().
 */
function emfield_theme() {
  return array(
    'emfield_handler_field_provider' => array(
      'arguments' => array('item' => NULL, 'field' => NULL, 'node' => NULL, 'values' => NULL, 'format' => NULL),
    ),
    'emfield_swfobject' =>array(
      'arguments' => array("url" => NULL, '$div_id' => NULL, 'width' => NULL, 'height' => NULL, 'version' => "8"),
      'path' => drupal_get_path('module', 'emfield') . '/includes/themes',
      'file' => 'emfield.themes.inc',
    ),
  );
}
