'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' => 'General', '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, 'weight' => -3, ); foreach (module_implements('emfield_info', TRUE) as $module) { $emfield_info = module_invoke($module, 'emfield_info'); $items['admin/content/emfield/'. $module] = array( 'title' => $emfield_info['#settings_title'], 'description' => $emfield_info['#settings_description'], 'file' => 'emfield.admin.inc', 'page callback' => 'drupal_get_form', 'page arguments' => array('emfield_module_settings', 3), 'access arguments' => array('administer site configuration'), 'type' => MENU_LOCAL_TASK, ); } $items['admin/content/emfield/obsolete'] = array( 'file' => 'emfield.admin.inc', 'title' => 'Disable obsolete provider', 'page callback' => 'emfield_disable_obsolete_provider', 'access arguments' => array('administer site configuration'), 'type' => MENU_CALLBACK, ); 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, 'weight' => 3, ); } 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)); $info = emfield_include_invoke($module, $item['provider'], 'info'); if ($info['module'] && module_hook($info['module'], 'emfield_status')) { $item['status'] = module_invoke($info['module'], 'emfield_status', $item, $field, $module); } 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. * * Note that emfield_retrieve_xml() in most cases will be better, as it's a * wrapper around simplexml. * * @param $provider * The string of the third party provider, such as 'youtube' or 'flickr'. * @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 with 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 to request XML: 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' or 'flickr'. * @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 with 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('emfield:request-header:'. $url, 'cache_emfield_xml')) { 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(); } // Cache the result. cache_set('emfield:request-header:'. $url, $result, 'cache_emfield_xml', 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 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"). * @return * An array of file objects optionally matching $provider. */ function emfield_system_list($module, $provider = NULL, $options = array()) { $files = $override_files = module_invoke_all('emfield_providers', $module, $provider); // $files = drupal_system_listing("$provider\.inc$", drupal_get_path('module', $module) ."/providers", 'name', 0); // $files = array_merge($files, $override_files); ksort($files); foreach ($files as $provider => $file) { emfield_include_list($file); if (!function_exists($module .'_'. $provider .'_info')) { emfield_include_list($file, TRUE); unset($files[$provider]); if (function_exists($module .'_'. $provider .'_obsolete') && variable_get('emfield_'. $module .'_allow_'. $provider, TRUE)) { if (isset($options['suppress_errors']) && $options['suppress_errors']) { continue; } $error = t('Attempted to load obsolete provider: %provider at @file.', array('%provider' => $provider, '@file' => $file->filename)); emfield_set_error($error); if (user_access('administer site configuration')) { drupal_set_message($error, error); call_user_func($module .'_'. $provider .'_obsolete'); drupal_set_message(t('You may also choose to !turn_off this warning about the missing or obsolete Embedded Media Field %provider provider file.', array('%provider' => $provider, '!turn_off' => l(t('turn off'), 'admin/content/emfield/obsolete/'. $module .'/'. $provider, array('query' => 'destination='. $_GET['q'])))), 'error'); } } } } return $files; } /** * Maintains a list of all loaded include files. * * @param $file * Optional; a file object (from emfield_system_list()) to be included. * @param $remove * Optional boolean; if TRUE, then remove the file from the list. * @return * An array of all loaded includes (without the .inc extension). */ function emfield_include_list($file = NULL, $remove = FALSE) { static $list = array(); if ($file && $file->filename && !isset($list[$file->filename])) { include_once('./'. $file->filename); $list[$file->filename] = $file->name; } if ($file && $remove) { unset($list[$file->filename]); } 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. However, it's possible this was never extended beyond emvideo. * @TODO: Allow views listings of other supported modules. */ 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); // @TODO: This hook no longer exists in D6. $db_info = content_database_info($field); $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); } } /** * Allow providers to create their own themes. * * @TODO: Remove this once we've moved all providers outside emfield, as their * wrapping modules can use standard Drupal hooks. */ 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; } /** * Allow providers to create their own menus. * * @TODO: Remove this once we've moved all providers outside emfield, as their * wrapping modules can use standard Drupal hooks. */ 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 (!isset($path) || $reset) { if (module_exists('flvmediaplayer')) { $path = variable_get('flvmediaplayer_path', drupal_get_path('module', 'flvmediaplayer') .'/mediaplayer.swf'); } else if ($reset || ($path = variable_get('emfield_flvmediaplayer_url', NULL) && !$path)) { $path = _emfield_autodiscover_path('(^player-viral\.swf$|^player\.swf$|^mediaplayer\.swf$)'); 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)) { $path = _emfield_autodiscover_path('(^imagerotator\.swf$)'); variable_set('emfield_imagerotator_url', $path); } } return $path; } /** * Search site library paths for the specific pattern. */ function _emfield_autodiscover_path($pattern) { foreach (array('libraries', 'plugins', 'modules') as $folder) { $files = drupal_system_listing($pattern, $folder, 'basename', 0); if (!empty($files)) { $file = array_pop($files); return $file->filename; } } } /** * 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_handler_field_status' => 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', ), ); } /** * A wrapper around simplexml to retrieve a given XML file. * * @param $url * The URL to the XML to retrieve. * @param $display_errors * Optional; if TRUE, then we'll display errors to the end user. They'll be * logged to the watchdog in any case. * @param $refresh * Optional; if TRUE, then we'll force a new load of the XML. Otherwise, * a cached version will be retrieved if possible. * @return * A fully populated object, or FALSE on an error. */ function emfield_retrieve_xml($url, $display_errors = FALSE, $refresh = FALSE) { module_load_include('inc', 'emfield', 'includes/emfield.xml'); return _emfield_retrieve_xml($url, $display_errors, $refresh); } /** * This will audit all nodes to ensure all emfield providers are present. * * The function will pass through all emfield fields to see if there is any * content in the system without a provider. * * @return array * An array of all missing providers. Ideally the array will be empty. */ function emfield_audit() { module_load_include('inc', 'emfield', 'includes/emfield.audit'); return _emfield_audit(); } /** * Implementation of hook_init(). */ function emfield_init() { global $emfield_registered_classes; // Build our media object class registry. foreach (module_implements('emfield_register') as $module) { foreach (module_invoke($module, 'emfield_register') as $class_name => $class) { $emfield_registered_classes[$class_name] = is_array($class) ? $class : array(); if (!isset($emfield_registered_classes[$class_name]['class_name'])) { $emfield_registered_classes[$class_name]['class_name'] = $class_name; } if (!isset($emfield_registered_classes[$class_name]['name'])) { $emfield_registered_classes[$class_name]['name'] = $class_name; } if (!isset($emfield_registered_classes[$class_name]['path'])) { $emfield_registered_classes[$class_name]['path'] = drupal_get_path('module', $module); } if (!isset($emfield_registered_classes[$class_name]['file'])) { $emfield_registered_classes[$class_name]['file'] = $class_name .'.inc'; } } } // Ensure the proper files are loaded when a new media object is initiated. spl_autoload_register('emfield_autoload'); } /** * Autoload the media object classes when needed. */ function emfield_autoload($class_name) { global $emfield_registered_classes; if (isset($emfield_registered_classes[$class_name])) { include_once($emfield_registered_classes[$class_name]['path'] .'/'. $emfield_registered_classes[$class_name]['file']); } } /** * Builds and returns a media object based on the parsed URL. */ function emfield_media($url, $overrides = array()) { global $emfield_registered_classes; // First parse the URL. foreach ($emfield_registered_classes as $provider => $class) { if ($class['parse callback'] && $class['class_name']) { if ($parsed = $class['parse callback']($url, $overrides)) { // If we have a provider class, then implement and return it. return new $class['class_name']($parsed['code'], $overrides); } } } }