array('administer oembed presets'), 'file' => 'oembedcore.admin.inc', ); $items['admin/build/oembed'] = array( 'title' => 'OEmbed', 'description' => 'Admin overview of OEmbed.', 'page callback' => 'oembedcore_list_preset', ) + $base; $items['admin/build/oembed/preset'] = array( 'title' => 'Presets', 'description' => 'Add, edit and remove oembed preset from the system.', 'page callback' => 'oembedcore_list_preset', 'type' => MENU_DEFAULT_LOCAL_TASK, ) + $base; $items['admin/build/oembed/preset/list'] = array( 'title' => 'List presets', 'page callback' => 'oembedcore_list_preset', 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10, ) + $base; $items['admin/build/oembed/preset/add'] = array( 'title' => 'Add preset', 'page callback' => 'oembedcore_add_preset', 'type' => MENU_LOCAL_TASK, ) + $base; $items['admin/build/oembed/preset/%oembedcore_preset/edit'] = array( 'title' => 'Edit preset', 'page callback' => 'oembedcore_edit_preset', 'page arguments' => array(4), 'type' => MENU_LOCAL_TASK, ) + $base; $items['admin/build/oembed/preset/%oembedcore_preset/export'] = array( 'title' => 'Export preset', 'page callback' => 'drupal_get_form', 'page arguments' => array('oembedcore_export_preset', 4), 'type' => MENU_LOCAL_TASK, ) + $base; $items['admin/build/oembed/preset/%oembedcore_preset/delete'] = array( 'title' => 'Delete preset', 'page callback' => 'drupal_get_form', 'page arguments' => array('oembedcore_delete_confirm_preset', 4), 'type' => MENU_CALLBACK, ) + $base; $items['admin/build/oembed/preset/%oembedcore_preset/disable'] = array( 'page callback' => 'oembedcore_disable_preset', 'page arguments' => array(4), 'type' => MENU_CALLBACK, ) + $base; $items['admin/build/oembed/preset/%oembedcore_preset/enable'] = array( 'page callback' => 'oembedcore_enable_preset', 'page arguments' => array(4), 'type' => MENU_CALLBACK, ) + $base; $items['admin/build/oembed/provider'] = array( 'title' => 'Providers', 'description' => 'Add, edit and remove oembed providers from the system.', 'page callback' => 'oembedcore_list_provider', 'type' => MENU_LOCAL_TASK, ) + $base; $items['admin/build/oembed/provider/list'] = array( 'title' => 'List providers', 'page callback' => 'oembedcore_list_provider', 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10, ) + $base; $items['admin/build/oembed/provider/add'] = array( 'title' => 'Add provider', 'page callback' => 'oembedcore_add_provider', 'type' => MENU_LOCAL_TASK, ) + $base; $items['admin/build/oembed/provider/%oembedcore_provider/edit'] = array( 'title' => 'Edit provider', 'page callback' => 'oembedcore_edit_provider', 'page arguments' => array(4), 'type' => MENU_LOCAL_TASK, ) + $base; $items['admin/build/oembed/provider/%oembedcore_provider/export'] = array( 'title' => 'Export provider', 'page callback' => 'drupal_get_form', 'page arguments' => array('oembedcore_export_provider', 4), 'type' => MENU_LOCAL_TASK, ) + $base; $items['admin/build/oembed/provider/%oembedcore_provider/delete'] = array( 'title' => 'Delete provider', 'page callback' => 'drupal_get_form', 'page arguments' => array('oembedcore_delete_confirm_provider', 4), 'type' => MENU_CALLBACK, ) + $base; $items['admin/build/oembed/provider/%oembedcore_provider/disable'] = array( 'page callback' => 'oembedcore_disable_provider', 'page arguments' => array(4), 'type' => MENU_CALLBACK, ) + $base; $items['admin/build/oembed/provider/%oembedcore_provider/enable'] = array( 'page callback' => 'oembedcore_enable_provider', 'page arguments' => array(4), 'type' => MENU_CALLBACK, ) + $base; return $items; } /** * Implementation of hook_theme(). */ function oembedcore_theme() { $path = drupal_get_path('module', 'oembedcore') . '/theme'; return array( 'oembed' => array( 'template' => 'oembed', 'file' => 'oembedcore_theme.inc', 'path' => $path, 'arguments' => array('embed' => NULL), ), ); } /** * Implementation of hook_default_oembedcore_provider(). */ function oembedcore_default_oembedcore_provider() { $providers = array(); $provider = new stdClass; $provider->disabled = TRUE; /* Edit this to true to make a default provider disabled initially */ $provider->name = 'viddler'; $provider->title = 'Viddler'; $provider->endpoint = 'http://lab.viddler.com/services/oembed/'; $provider->scheme = 'http://*.viddler.com/*'; $providers['viddler'] = $provider; $provider = new stdClass; $provider->disabled = TRUE; /* Edit this to true to make a default provider disabled initially */ $provider->name = 'flickr'; $provider->title = 'Flickr'; $provider->endpoint = 'http://www.flickr.com/services/oembed/'; $provider->scheme = 'http://*.flickr.com/* http://flickr.com/*'; $providers['flickr'] = $provider; $provider = new stdClass; $provider->disabled = TRUE; /* Edit this to true to make a default provider disabled initially */ $provider->name = 'qik'; $provider->title = 'Qik'; $provider->endpoint = 'http://qik.com/api/oembed.json'; $provider->scheme = 'http://qik.com/video/* http://qik.com/*'; $providers['qik'] = $provider; $provider = new stdClass; $provider->disabled = TRUE; /* Edit this to true to make a default provider disabled initially */ $provider->name = 'revision3'; $provider->title = 'Revision3'; $provider->endpoint = 'http://revision3.com/api/oembed/'; $provider->scheme = 'http://*.revision3.com/*'; $providers['revision3'] = $provider; $provider = new stdClass; $provider->disabled = TRUE; /* Edit this to true to make a default provider disabled initially */ $provider->name = 'vimeo'; $provider->title = 'Vimeo'; $provider->endpoint = 'http://www.vimeo.com/api/oembed.json'; $provider->scheme = 'http://www.vimeo.com/groups/*/videos/* http://www.vimeo.com/* http://vimeo.com/groups/*/videos/* http://vimeo.com/*'; $providers['vimeo'] = $provider; $provider = new stdClass; $provider->disabled = TRUE; /* Edit this to true to make a default provider disabled initially */ $provider->name = 'youtube'; $provider->title = 'YouTube'; $provider->endpoint = 'http://www.youtube.com/oembed'; $provider->scheme = 'http://*.youtube.com/watch*'; $providers['youtube'] = $provider; return $providers; } /** * Returns the provider for a url. * * @param string $url * Teh url to get the provider for. * @return mixed * A valid callback or FALSE */ function oembedcore_get_provider($url, &$matches) { $host = _oembedcore_get_host($url); if ($host) { $providers = oembedcore_providers($host); foreach ($providers as $regex => $info) { if (preg_match($regex, $url, $matches)) { return $info; } } } return FALSE; } /** * A utility function to get the base domain from a url. * * @param string $uri * The uri to get the domain form * @return string * The domain or NULL */ function _oembedcore_get_host($uri) { $matches = array(); if (preg_match('/^https?\:\/\/([^\/]+)/', $uri, $matches)) { $matches = explode('.', $matches[1]); $match_count = count($matches); if ($match_count > 1) { return $matches[$match_count - 2] . '.' . $matches[$match_count - 1]; } else { return $matches[0]; } } return NULL; } /** * Returns all the registered providers, or the providers for a specific host. * * @param string $host * Optional. Supply a hostname if you only want the provider patterns for a specific host. * @return array */ function oembedcore_providers($url_host = NULL) { static $providers; if (!$providers) { $cache_key = 'oembedcore:providers'; if (($cache = cache_get($cache_key)) && isset($cache->data)) { $providers = $cache->data; } else { $providers = array(); $modules = module_implements('oembedprovider'); foreach ($modules as $module) { $ps = call_user_func($module . '_oembedprovider'); foreach ($ps as $pattern => $info) { $host = _oembedcore_get_host($pattern); $regex_pattern = '/' . str_replace('\*', '(.+)', preg_quote($pattern, '/')) . '/'; $providers[$host][$regex_pattern] = $info; } } $provider_definitions = oembedcore_provider_load_all(); foreach ($provider_definitions as $provider_definition) { if (!$provider_definition->disabled) { $schemes = explode("\n", $provider_definition->scheme); foreach ($schemes as $scheme) { $host = _oembedcore_get_host($scheme); $regex_pattern = '/' . str_replace('\*', '(.+)', preg_quote($scheme, '/')) . '/'; $providers[$host][$regex_pattern] = array('endpoint' => $provider_definition->endpoint); } } } drupal_alter('oembedprovider', $providers); foreach ($providers as $host => &$patterns) { uksort($patterns, '_oembedcore_specificity_compare'); } cache_set($cache_key, $providers); } } if ($url_host) { return isset($providers[$url_host]) ? $providers[$url_host] : array(); } return $providers; } /** * Helper function that compares the length of match expressions. */ function _oembedcore_specificity_compare($a, $b) { return strlen($b) - strlen($a); } /** * Fetch data for an embeddable URL. * * @param string $url * An external URL for the content to embed. * @param array $attributes * An associative array of attributes, with the following keys: * - 'maxwidth' * The maximum width of the embed, in pixels. * - 'maxheight' * The maximum height of the embed, in pixels. * @return * False or an object representing the embeddable data of the URL. */ function oembedcore_oembed_data($url, $attributes = array()) { $matches = array(); if ($provider = oembedcore_get_provider($url, $matches)) { return oembedcore_oembed_fetch($provider, $url, $matches, $attributes); } return FALSE; } function oembedcore_oembed_fetch($provider, $url, $matches, $attributes = array()) { global $_oembed_default_attributes; $embed = FALSE; if (!empty($_oembed_default_attributes)) { $attributes = array_merge($_oembed_default_attributes, $attributes); } $attributes['url'] = $url; $query = http_build_query($attributes, NULL, '&'); $source = isset($provider['callback']) ? $provider['callback'] : $provider['endpoint']; $cache_key = 'oembedcore:embed:' . md5($source . $url . $query); $cache = cache_get($cache_key); if ($cache && isset($cache->data)) { $embed = $cache->data; } else { if (!empty($provider['callback'])) { $embed = call_user_func($provider['callback'], $provider, $url, $matches, $attributes); if ($embed) { $embed = (object)$embed; } } else { $fetch_url = $provider['endpoint'] . '?' . $query; //TODO: Add alternative ways of fetching the content - like http client? $response = drupal_http_request($fetch_url); if (!$response->error) { $embed = json_decode($response->data); if (!is_object($embed)) { //TODO: Better error handling here $embed = new SimpleXMLElement($response->data); $embed = (object)get_object_vars($embed); if (!is_string($embed->title)) { $embed->title = ''; } } } } if ($embed) { $embed->original_url = $url; } $max_age = isset($embed->cache_age) ? intval($embed->cache_age) : empty($provider['callback']) ? 600 : 60; cache_set($cache_key, $embed, 'cache', time() + $max_age); } return $embed; } /** * To be used for HTML in cases where the HTML is cached independent of the theme - like in the case of input filters. */ function oembedcore_oembed_html($embed, $url) { //TODO: Maybe refactor into something that uses drupal_render()? $return = ''; switch ($embed->type) { case 'photo': $return = ''; break; case 'rich': case 'video': $return = '
'; break; case 'link': $return .= l($embed->title, $url, array('absolute' => TRUE, 'attributes' => array('class' => 'oembed-title oembed-link'))); break; default: } return $return; } // -------------------------------------------------------------------------- // Preset database info. /** * Clear presets cache on admin/build/modules form. */ function oembedcore_form_system_modules_alter(&$form, $form_state) { //Copied from imagecache - needed because other modules might contain presets which oembedfield uses and cck caches //TODO: Extract this and move to oembedfield if (module_exists('content')) { content_clear_type_cache(); } } /** * Create a new preset with defaults appropriately set from schema. */ function oembedcore_preset_new() { ctools_include('export'); return ctools_export_new_object('oembedcore_preset'); } /** * Load a single preset */ function oembedcore_preset_load($name) { ctools_include('export'); $result = ctools_export_load_object('oembedcore_preset', 'names', array($name)); if (isset($result[$name])) { return $result[$name]; } else { return FALSE; } } /** * Load all presets. */ function oembedcore_preset_load_all() { ctools_include('export'); return ctools_export_load_object('oembedcore_preset'); } /** * Write a preset to the database. */ function oembedcore_preset_save(&$preset) { $update = (isset($preset->pid)) ? array('pid') : array(); drupal_write_record('oembedcore_preset', $preset, $update); // Clear the content.module cache (refreshes the list of formatters provided by oembedfield.module). //TODO: Extract this and move to oembedfield if (module_exists('content')) { content_clear_type_cache(); drupal_rebuild_theme_registry(); } return $preset; } /** * Remove a preset. */ function oembedcore_preset_delete($preset) { db_query("DELETE FROM {oembedcore_preset} WHERE name = '%s' AND pid = %d", $preset->name, $preset->pid); // Clear the content.module cache (refreshes the list of formatters provided by oembedfield.module). //TODO: Extract this and move to oembedfield if (module_exists('content')) { content_clear_type_cache(); drupal_rebuild_theme_registry(); } } /** * Export a preset */ function oembedcore_preset_export($preset, $indent = '') { ctools_include('export'); $output = ctools_export_object('oembedcore_preset', $preset, $indent); return $output; } /** * Lists all available presets */ function oembedcore_preset_list() { $return = array(); $presets = oembedcore_preset_load_all(); foreach ($presets as $preset) { $return[$preset->name] = $preset->name; } return $return; } // -------------------------------------------------------------------------- // Preset database info. /** * Create a new provider with defaults appropriately set from schema. */ function oembedcore_provider_new() { ctools_include('export'); return ctools_export_new_object('oembedcore_provider'); } /** * Load a single provider. */ function oembedcore_provider_load($name) { ctools_include('export'); $result = ctools_export_load_object('oembedcore_provider', 'names', array($name)); if (isset($result[$name])) { return $result[$name]; } else { return FALSE; } } /** * Load all providers. */ function oembedcore_provider_load_all() { ctools_include('export'); return ctools_export_load_object('oembedcore_provider'); } /** * Write a provider to the database. */ function oembedcore_provider_save(&$provider) { $update = (isset($provider->pid)) ? array('pid') : array(); drupal_write_record('oembedcore_provider', $provider, $update); cache_clear_all('oembedcore:providers'); return $preset; } /** * Remove a provider. */ function oembedcore_provider_delete($provider) { db_query("DELETE FROM {oembedcore_provider} WHERE name = '%s' AND pid = %d", $provider->name, $provider->pid); cache_clear_all('oembedcore:providers'); } /** * Export a provider. */ function oembedcore_provider_export($provider, $indent = '') { ctools_include('export'); $output = ctools_export_object('oembedcore_provider', $provider, $indent); return $output; } /** * Lists all available providers. */ function oembedcore_provider_list() { $return = array(); $providers = oembedcore_provider_load_all(); foreach ($providers as $provider) { $return[$provider->name] = $provider->name; } return $return; }