oembedcore.module in oEmbed 6.0
Core functionality for oEmbed
File
oembedcore.moduleView source
<?php
/**
* @file
* Core functionality for oEmbed
*/
/**
* Implementation of hook_help().
*/
function oembedcore_help($path, $arg) {
switch ($path) {
case 'admin/help#oembedcore':
$output = '<p>' . t('oEmbed module will allow your Drupal site to embed content from <a href="@oembed">oEmbed</a>-providers as well as for the site to become an oEmbed-provider itself so that other oEmbed-enabled websites can easily embed your content.', array(
'@oembed' => 'http://www.oembed.com/',
)) . '</p>';
$output .= '<p>' . t('Create <a href="@preset">presets</a> to customize the way oEmbed content appears on your site.', array(
'@preset' => url('admin/build/oembed/preset'),
)) . '</p>';
$output .= '<p>' . t('Add or enable <a href="@provider">providers</a> to embed content from other sites.', array(
'@provider' => url('admin/build/oembed/provider'),
)) . '</p>';
return $output;
case 'admin/build/oembed':
case 'admin/build/oembed/preset':
$output = '<p>' . t('Presets are the dimensions and other display properties of content embedded on your site.') . '</p>';
return $output;
case 'admin/build/oembed/provider':
$output = '<p>' . t('Providers are other web sites with oEmbed endpoints whose content you can embed on your site.') . '</p>';
return $output;
}
}
/**
* Implementation of hook_perm().
*/
function oembedcore_perm() {
return array(
'administer oembed presets',
);
}
/**
* Implementation of hook_menu_alter().
*
* Instead of rewriting ctools export UI's hook_menu implementations, alter
* the callback items to have a common menu item.
*/
function oembedcore_menu_alter(&$items) {
// Create a new menu item where all oembed export UIs will be local tasks by
// copying the export UI's menu item that will become the default local task.
$items['admin/build/oembed'] = $items['admin/build/oembed/preset'];
$items['admin/build/oembed']['title'] = 'oEmbed';
$items['admin/build/oembed']['description'] = 'Admin overview of oEmbed.';
$items['admin/build/oembed/preset']['type'] = MENU_DEFAULT_LOCAL_TASK;
$items['admin/build/oembed/provider']['type'] = MENU_LOCAL_TASK;
}
/**
* 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
*
* @todo Make this more like drupal_match_path()
*/
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();
// oEmbed providers are local services that return content over callback
// function.
$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, '/')) . '/i';
$providers[$host][$regex_pattern] = $info;
}
}
// oEmbed provider definitions are remote web services.
$provider_definitions = oembedcore_provider_load_all();
foreach ($provider_definitions as $provider_definition) {
if (empty($provider_definition->disabled)) {
$schemes = preg_split("/(\r\n?|\n)/", $provider_definition->scheme);
foreach ($schemes as $scheme) {
$host = _oembedcore_get_host($scheme);
$regex_pattern = '/' . str_replace('\\*', '.*', preg_quote($scheme, '/')) . '/i';
$providers[$host][$regex_pattern] = (array) $provider_definition;
}
}
}
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)) {
$data =& $attributes;
$data['__drupal_alter_by_ref'] = array(
&$provider,
);
drupal_alter('oembed_request', $data, $url);
return oembedcore_oembed_fetch($provider, $url, $matches, $attributes);
}
return FALSE;
}
function oembedcore_oembed_fetch($provider, $url, $matches, $attributes = array()) {
$embed = FALSE;
$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 (!isset($response->error)) {
$embed = json_decode($response->data);
if (!is_object($embed)) {
try {
$embed = @new SimpleXMLElement($response->data);
$embed = (object) get_object_vars($embed);
if (!is_string($embed->title)) {
$embed->title = '';
}
} catch (Exception $e) {
watchdog('oembed', 'Could not parse response from %url.', array(
'%url' => $fetch_url,
), WATCHDOG_ERROR);
}
}
if (empty($embed->version) || empty($embed->type) || intval($embed->version) != 1) {
$embed = FALSE;
watchdog('oembed', 'Response from %url not a valid oEmbed response.', array(
'%url' => $fetch_url,
), WATCHDOG_ERROR);
}
}
else {
watchdog('oembed', 'Error fetching data from %url.', array(
'%url' => $fetch_url,
), WATCHDOG_ERROR);
}
}
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 = '<span class="oembed">';
if (!empty($embed->title)) {
$return .= l($embed->title, $url, array(
'absolute' => TRUE,
'attributes' => array(
'class' => 'oembed-title',
),
));
}
$img_attributes = array(
'src' => check_url($embed->url),
'alt' => empty($embed->title) ? t('Embedded image') : $embed->title,
);
if (!empty($embed->provider_name)) {
$img_attributes['alt'] .= ', ' . t('on') . ' ' . $embed->provider_name;
}
$return .= ' ' . l('<img' . drupal_attributes($img_attributes) . ' />', $url, array(
'html' => TRUE,
'absolute' => TRUE,
'attributes' => array(
'class' => 'oembed-photo oembed-content',
),
));
$return .= '</span>';
break;
case 'rich':
case 'video':
$return = '<div class="oembed">';
if (!empty($embed->title)) {
$return .= l($embed->title, $url, array(
'absolute' => TRUE,
'attributes' => array(
'class' => 'oembed-title',
),
));
}
$return .= ' <span class="oembed-content oembed-' . ($embed->type == 'video' ? 'video' : 'rich') . '">' . $embed->html . '</span>';
$return .= '</div>';
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();
}
}
/**
* Implement hook_ctools_plugin_directory().
*/
function oembedcore_ctools_plugin_directory($module, $plugin) {
if ($module == 'ctools' && $plugin == 'export_ui') {
return 'plugins/' . $plugin;
}
}
/**
* 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', 'cache');
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', 'cache');
}
/**
* 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;
}
Functions
Name | Description |
---|---|
oembedcore_ctools_plugin_directory | Implement hook_ctools_plugin_directory(). |
oembedcore_default_oembedcore_provider | Implementation of hook_default_oembedcore_provider(). |
oembedcore_form_system_modules_alter | Clear presets cache on admin/build/modules form. |
oembedcore_get_provider | Returns the provider for a url. |
oembedcore_help | Implementation of hook_help(). |
oembedcore_menu_alter | Implementation of hook_menu_alter(). |
oembedcore_oembed_data | Fetch data for an embeddable URL. |
oembedcore_oembed_fetch | |
oembedcore_oembed_html | To be used for HTML in cases where the HTML is cached independent of the theme - like in the case of input filters. |
oembedcore_perm | Implementation of hook_perm(). |
oembedcore_preset_delete | Remove a preset. |
oembedcore_preset_export | Export a preset |
oembedcore_preset_list | Lists all available presets |
oembedcore_preset_load | Load a single preset |
oembedcore_preset_load_all | Load all presets. |
oembedcore_preset_new | Create a new preset with defaults appropriately set from schema. |
oembedcore_preset_save | Write a preset to the database. |
oembedcore_providers | Returns all the registered providers, or the providers for a specific host. |
oembedcore_provider_delete | Remove a provider. |
oembedcore_provider_export | Export a provider. |
oembedcore_provider_list | Lists all available providers. |
oembedcore_provider_load | Load a single provider. |
oembedcore_provider_load_all | Load all providers. |
oembedcore_provider_new | Create a new provider with defaults appropriately set from schema. |
oembedcore_provider_save | Write a provider to the database. |
oembedcore_theme | Implementation of hook_theme(). |
_oembedcore_get_host | A utility function to get the base domain from a url. |
_oembedcore_specificity_compare | Helper function that compares the length of match expressions. |