emapi.module in Embedded Media Field 6.3
Provides an API for parsing, storage, and display of third party media.
File
emapi/emapi.moduleView source
<?php
/**
* @file
* Provides an API for parsing, storage, and display of third party media.
*/
/* ***************************************** */
/* INCLUDES */
/* ***************************************** */
// A registry of variable_get defaults.
include_once 'includes/emapi.variables.inc';
/**
* Implementation of hook_menu().
*/
function emapi_menu() {
$items = array();
$items['admin/content/emapi'] = array(
'page callback' => 'emapi_admin_list_page',
'title' => 'Embedded media',
'description' => 'Administration list of embedded media.',
'access arguments' => array(
'administer embedded media',
),
'file' => 'includes/emapi.admin.inc',
);
$items['emapi/parse/json'] = array(
'page callback' => 'emapi_parse_json',
'title' => 'Parse media',
'description' => 'Automatically derive a media object from a parsed URL or embed code.',
'access arguments' => array(
'administer embedded media',
),
'file' => 'includes/emapi.parse.inc',
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Implementation of hook_init().
*/
function emapi_init() {
emapi_get_provider_classes();
// Ensure the proper files are loaded when a new media object is initiated.
spl_autoload_register('emapi_autoload');
}
/**
* Implementation of hook_flush_caches().
*/
function emapi_flush_caches() {
return array(
'cache_emapi_xml',
);
}
/**
* Builds a registry of Media provider classes.
*
* Each module supporting a Media provider will need to implement
* hook_emapi_register, which will need to return an associated array keyed by
* the scheme, with an array containing at least the following key => value
* pairs. Note that the scheme portion of the URI this class supports is in the
* form of scheme://identifier/id.
* 'class_name' => The actual name of the class.
* The following key => value pairs are optional, and will otherwise be
* automatically derived:
* 'name' => The human-readable name of the scheme.
* 'description' => A description of the scheme.
* 'path' => The path where the class file resides.
* 'file' => The file containing the class definition.
* 'module' => The module defining the class.
* 'url' => The URL to the remote media provider, if applicable.
* The following key => value pair will be automatically set to the association
* and cannot be overridden:
* 'scheme' => The scheme portion of the URI.
*
* @param string $scheme
* (Optional) The scheme of the specific class registration to return.
* @param boolean $reset
* (Optional) If TRUE, then reset the registration.
* @return array
* If $scheme is specified, then return only the specified class array, or NULL
* if there is no such registered class. Otherwise, return the entiry registry.
*/
function emapi_get_provider_classes($scheme = NULL, $reset = FALSE) {
static $emapi_registered_classes;
if ($reset || !isset($emapi_registered_classes)) {
$emapi_registered_classes = array();
// Build our media object class registry.
foreach (module_implements('emapi_register') as $module) {
foreach (module_invoke($module, 'emapi_register') as $scheme_name => $class) {
$emapi_registered_classes[$scheme_name] = is_array($class) ? $class : array();
$emapi_registered_classes[$scheme_name]['scheme'] = $scheme_name;
if (!isset($emapi_registered_classes[$scheme_name]['name'])) {
$emapi_registered_classes[$scheme_name]['name'] = t($scheme_name);
}
if (!isset($emapi_registered_classes[$scheme_name]['description'])) {
$emapi_registered_classes[$scheme_name]['description'] = t('Class definition for @scheme.', array(
'@scheme' => $scheme_name,
));
}
if (!isset($emapi_registered_classes[$scheme_name]['path'])) {
$emapi_registered_classes[$scheme_name]['path'] = drupal_get_path('module', $module);
}
if (!isset($emapi_registered_classes[$scheme_name]['file'])) {
$emapi_registered_classes[$scheme_name]['file'] = $class_name . '.inc';
}
if (!isset($emapi_registered_classes[$scheme_name]['module'])) {
$emapi_registered_classes[$scheme_name]['module'] = $module;
}
}
}
}
if (isset($scheme) && isset($emapi_registered_classes[$scheme])) {
return $emapi_registered_classes[$scheme];
}
else {
if (!isset($scheme)) {
return $emapi_registered_classes;
}
}
}
/**
* Autoload the media object classes when needed.
*/
function emapi_autoload($class_name) {
if ($class_name == 'EmapiMedia') {
module_load_include('inc', 'emapi', 'includes/emapi.class.media');
}
else {
if ($class = emapi_get_provider_class_by_class_name($class_name)) {
include_once $class['path'] . '/' . $class['file'];
}
}
}
/**
* Return the registered EmAPI class specified by name.
*/
function emapi_get_provider_class_by_class_name($class_name = NULL, $reset = FALSE) {
static $classes;
if (!isset($classes) || $reset) {
$classes = array();
$provider_classes = emapi_get_provider_classes();
foreach ($provider_classes as $scheme => $class) {
$classes[$class['class_name']] = $class;
}
}
if (isset($class_name)) {
return $classes[$class_name];
}
return $classes;
}
/**
* 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 emapi_retrieve_xml($url, $display_errors = FALSE, $refresh = FALSE) {
module_load_include('inc', 'emapi', 'includes/emapi.xml');
return _emapi_retrieve_xml($url, $display_errors, $refresh);
}
/**
* Returns the scheme of a URI (e.g. a stream).
*
* Note that this function is lifted from Drupal 7's file_uri_scheme().
*
* @param $uri
* A stream, referenced as "scheme://target".
* @return
* A string containing the name of the scheme, or FALSE if none. For example,
* the URI "youtube://v/3gfh6asey" would return "youtube".
*/
function emapi_uri_scheme($uri) {
$data = explode('://', $uri, 2);
return count($data) == 2 ? $data[0] : FALSE;
}
/**
* Returns the registered class for a specific provider.
*
* @param string $uri
* A stream, referenced as "scheme://target".
* @return string
* The registered class, or NULL if it's an unsupported URI.
*/
function emapi_get_provider_class($uri) {
$class = emapi_get_provider_classes(emapi_uri_scheme($uri));
if (is_array($class) && $class['class_name']) {
return $class['class_name'];
}
}
/**
* Parses a URL or embed code into a media object.
*
* @param string $url
* The URL or embed code to parse.
* @return mixed
* The fully populated media object, or FALSE.
*/
function emapi_parse($url) {
foreach (emapi_get_provider_classes() as $class) {
if (class_exists($class['class_name'])) {
$media = new $class['class_name']();
if ($media
->parse($url)) {
$media = emapi_media_from_uri($media->uri);
return $media;
}
}
}
return FALSE;
}
/**
* Loads a media object based on the given URI.
*
* @param string $uri
* A stream, referenced as "scheme://target".
* @return mixed
* The fully populated media object, or FALSE.
*/
function emapi_media_from_uri($uri) {
$media =& emapi_static('emapi_media', array());
// First check to see if we've already loaded this media.
foreach ($media as $emid => $item) {
if ($item->uri == $uri) {
return $item;
}
}
// Next see if the item is in the db.
$results = db_query("SELECT emid, uri, uid, status, timestamp FROM {emapi_media} WHERE uri = '%s'", $uri);
if ($result = db_fetch_object($results)) {
$media[$result->emid] = emapi_media_from_db_result($result);
return $media[$result->emid];
}
// Finally we simply create a new media object.
if (($class = emapi_get_provider_class($uri)) && class_exists($class)) {
global $user;
$item = new $class($uri);
$item
->set_uid($user->uid);
$item
->set_status(EMAPI_STATUS_PERMANENT);
$item
->set_timestamp(time());
drupal_alter('emapi_media', $item);
return $item;
}
// No media matches the given URI.
return FALSE;
}
/**
* Create a new media object from a db result.
*
* @param object $result
* The db object returned from the db.
* @return mixed
* The media object, or NULL if there's no class available for the scheme.
*/
function emapi_media_from_db_result($result) {
if (($class = emapi_get_provider_class($result->uri)) && class_exists($class)) {
$media = new $class($result->uri);
$media
->set_emid($result->emid);
$media
->set_uid($result->uid);
$media
->set_status($result->status);
$media
->set_timestamp($result->timestamp);
drupal_alter('emapi_media', $media);
}
return $media;
}
/**
* Load one or more fully populated media objects.
*
* @param array $emids
* An array of unique integers corresponding to the media ID's.
* @return mixed
* The fully populated media object, or FALSE.
*/
function emapi_media_load_multiple($emids) {
$media =& emapi_static('emapi_media', array());
if (!empty($emids)) {
// If any media were previously loaded, remove from the ids still to load.
$emids = array_flip($emids);
$ids_to_load = array_keys(array_diff_key($emids, $media));
if (!empty($ids_to_load)) {
$results = db_query("SELECT emid, uri, uid, status, timestamp FROM {emapi_media} WHERE emid IN (" . db_placeholders($ids_to_load) . ")", $ids_to_load);
while ($result = db_fetch_object($results)) {
$media[$result->emid] = emapi_media_from_db_result($result);
module_invoke_all("emapi_media_load", $media[$result->emid]);
}
}
// Ensure that the returned array is ordered the same as the original
// $ids array if this was passed in and remove any invalid ids.
// Remove any invalid ids from the array.
$requested_ids = array_intersect_key($media, $emids);
$returned_ids = array();
foreach ($emids as $id => $item) {
if ($requested_ids[$id]) {
$returned_ids[$id] = $requested_ids[$id];
}
}
}
return $returned_ids;
}
/**
* Load a single media object.
*
* @param integer $emid
* The unique ID for the media.
* @return mixed
* Either the desired media object, or NULL if not found.
*/
function emapi_media_load($emid) {
$media = emapi_media_load_multiple(array(
$emid,
));
return $media[$emid];
}
/**
* Save a media object to the database.
*
* @param object &$media
* The media object to save.
*/
function emapi_media_save(&$media) {
module_invoke_all('emapi_media_presave', $media);
if ($media->emid) {
drupal_write_record('emapi_media', $media, 'emid');
module_invoke_all('emapi_media_update', $media);
}
else {
if ($media) {
drupal_write_record('emapi_media', $media);
module_invoke_all('emapi_media_insert', $media);
}
}
}
/**
* Delete a media object from the database.
*
* @param integer $emid
* The unique identifier of the media to delete.
*/
function emapi_media_delete($emid) {
$media =& emapi_static('emapi_media', array());
$item = emapi_media_load($emid);
if ($item) {
unset($media[$emid]);
db_query("DELETE FROM {emapi_media} WHERE emid = %d", $emid);
module_invoke_all('emapi_media_delete', $item);
$link = l($item
->get_uri(), $item
->url());
$class = emapi_get_provider_classes(emapi_uri_scheme($item
->get_uri()));
watchdog('emapi', '@provider: deleted !link.', array(
'@provider' => $class['name'],
'!link' => $link,
));
drupal_set_message(t('@provider !link has been deleted.', array(
'@provider' => $class['name'],
'!link' => $link,
)));
}
}
/**
* Backport of d7's drupal_static().
*/
function &emapi_static($name, $default_value = NULL, $reset = FALSE) {
static $data = array(), $default = array();
if (!isset($name)) {
// All variables are reset. This needs to be done one at a time so that
// references returned by earlier invocations of drupal_static() also get
// reset.
foreach ($default as $name => $value) {
$data[$name] = $value;
}
// As the function returns a reference, the return should always be a
// variable.
return $data;
}
if ($reset) {
// The reset means the default is loaded.
if (array_key_exists($name, $default)) {
$data[$name] = $default[$name];
}
else {
// Reset was called before a default is set and yet a variable must be
// returned.
return $data;
}
}
elseif (!array_key_exists($name, $data)) {
// Store the default value internally and also copy it to the reference to
// be returned.
$default[$name] = $data[$name] = $default_value;
}
return $data[$name];
}
Functions
Name | Description |
---|---|
emapi_autoload | Autoload the media object classes when needed. |
emapi_flush_caches | Implementation of hook_flush_caches(). |
emapi_get_provider_class | Returns the registered class for a specific provider. |
emapi_get_provider_classes | Builds a registry of Media provider classes. |
emapi_get_provider_class_by_class_name | Return the registered EmAPI class specified by name. |
emapi_init | Implementation of hook_init(). |
emapi_media_delete | Delete a media object from the database. |
emapi_media_from_db_result | Create a new media object from a db result. |
emapi_media_from_uri | Loads a media object based on the given URI. |
emapi_media_load | Load a single media object. |
emapi_media_load_multiple | Load one or more fully populated media objects. |
emapi_media_save | Save a media object to the database. |
emapi_menu | Implementation of hook_menu(). |
emapi_parse | Parses a URL or embed code into a media object. |
emapi_retrieve_xml | A wrapper around simplexml to retrieve a given XML file. |
emapi_static | Backport of d7's drupal_static(). |
emapi_uri_scheme | Returns the scheme of a URI (e.g. a stream). |