/** * API documentation for the Media module. */ The Media module provides a robust API for developers to extend functionality in useful and novel ways. CAUTION: This is pretty old! Architecture ------------ To understand the API, it is first important to understand the underlying architecture and the decisions behind its current implementation. Stream Wrappers --------------- First, the Media module makes heavy use of the core Stream Wrappers now provided with Drupal 7. Streams are classes that encapsulate PHP file functions, allowing an automatic override when calling the basic function. For instance, a wrapper implementing an Amazon S3 Stream might override the file_get_contents() using ->stream_open(), or a Flickr Stream Wrapper might implement its own ->getExternalUrl to return the HTML URI for a specific Flickr image. See http://api.drupal.org/file/includes/stream_wrappers.inc/7 for more information about Stream Wrappers in Drupal. Schemes ------- All Stream Wrappers will be registered to handle a specific scheme, which is the part of a URI before ://, such as core Drupal's public:// and private:// schemes. (Technically, a scheme only requires :, but a bug in PHP 5.2 requires ://, so Drupal currently keeps the same requirement.) The target after the scheme:// will be a unique identifier that the implementing Stream Wrapper will use to determine the file resource being accessed. For instance, public://my-document.txt might refer to a local file stored in the server at /sites/example.com/files/my-document.txt, while a URI of youtube://fe3fg8u34i might be the video stored at http://youtube.com/v/fe3fg8u34i, and flickr://photoset/224 might use a lookup table to determine this is a photoset accessed at http://flickr.com/user/markam/photoset/325hsd89. All files in Drupal are stored in the database with this unique URI, in addition to its unique serial FID. In general, file objects are accessed and loaded by the URI, which will automatically use the correct stream wrapper implementation for its scheme. File Field Widget ----------------- The Media module extends the core File field to make use of its browser for editors, which is in turn exposed for other modules to extend. It does this by create a new widget definition, defining a File (media) 'generic' file widget, and suppressing the original File widget definition to avoid confusion. All existing file fields will be converted to this new widget on installation of the module, and if uninstalled, any defined media_generic file fields will be reverted to their original definition to avoid loss of data. Media Formatters ---------------- By default, the File (media) widget will use the original display behavior, which is to display a generic icon followed by a link to the file. However, in many (if not most) cases, a site administrator will want to display media in very specific ways. For instance, they might want an image uploaded to be displayed as a cropped thumbnail, as with any Flickr images attached to that field, while a YouTube video might be displayed as a thumbnail that pops up in a Shadowbox, and finally a PDF might be displayed in an iFrame. And that's only when it's displayed in a node teaser... To manage the various display formatting needs of an editor, the Media module offers a Media Style API for other modules to implement and extend. Media Styles of various mimetypes are grouped together and made available as new formatters for field display, whether for a node, a comment, in a view, or elsewhere. To implement a new Media Style, a module needs to register itself for a specific mimetype, with the following hook. Note that Media styles will be properly namespaced by the module, to avoid conflicts. function hook_media_styles($mimetype = NULL) { switch ($mimetype) { case 'video/x-youtube': return array( 'youtube_video' => t('YouTube Video'), 'youtube_thumbnail' => t('YouTube Thumbnail'), 'youtube_shadowbox' => t('YouTube Shadowbox'), 'youtube_link' => t('Youtube (link to original)'), case 'image/x-flickr': $styles = array( 'flickr__original' => t('Flickr (Original size)'), ); foreach (image_styles() as $style_name => $style) { $styles[$style_name] = t('Flickr (@style)', array('@style' => $style->name)); } return $styles; } } These styles will be available from the Media Styles configuration page, where multiple formatters can be grouped together to create new formatter Style bundles, available and intelligently applied to files of the appropriate mimetypes. For instance, a new Media Style might be created, named 'Small image', which will bundle an Image style for the various image mimetypes, another for Flickr images, a shadowbox for YouTube thumbnails, and a fallback to a size styled File icon. Then this style would be made available as a display formatter, and the Media module will apply the correct style for the mimetype of the particular instance. A module may also define default Media styles to be made available, by implementing hook_media_default_style_bundles(). Unlike the individual Media Styles, Media Style bundles are not namespaced by module. If two or more modules use the same Style bundle names, the behavior is undefined. Also note that the administrator may override a specific Style bundle, for instance by replacing the Style for a specific mimetype. function hook_media_default_style_bundles() { return array( 'shadowbox_images' => array( 'label' => t('Shadowbox images'), 'mimetypes' => array( 'image/*' => 'mymodule_image_shadowbox', 'video/*' => 'mymodule_video_shadowbox', '*' => 'mymodule_default_shadowbox', ), ), ); } @TODO convert existing file fields to media_generic on hook_install convert existing media_generic to file fields on hook_uninstall allow theme_file_icon file directory override in widget display settings (Requires http://drupal.org/node/650732) create new default file icons and set its folder as the new default maybe instead/in addition have fallbacks if icon not present? rename image style square_thumbnail to use the media_ namespace review Media Styles for feasibility, usability, and architecture create Media Styles UI .inc file look at hook_field_info_alter to see if we can affect file widget that way CLEAN CRUFT (lots of functions that no longer apply or need to be rethought) why do we want to override the file field widget again? should we also move 'media_styles' to its own module, perhaps file_styles? in media_field_formatter_info(), should 'field types' => array('media_generic', 'file'), be only one or other?