'admin/media/swf',
'title' => t('SWF Tools'),
'callback' => 'swftools_admin',
'access' => $swf_admin,
'position' => 'left',
'description' => t('SWF Tools provide integration with Macromedia Flash related methods and tools like Video Players, MP3 Players and Image Viewers'),
);
$items[] = array(
'path' => 'admin/media/swf/embed',
'title' => t('Embedding settings'),
'description' => t('Settings specific to Flash embedding. Object and embed attributes can be set here.'),
'weight' => -2,
);
$items[] = array(
'path' => 'admin/media/swf/handling',
'title' => t('File handling'),
'description' => t('Flash players and handling for various file types.'),
'weight' => -1,
);
$items = array_merge($items, genericplayers_menu(TRUE));
}
return $items;
}
/**
* Show the administration forms, depending on the url. In general, SWF Tools
* player integration modules allow SWF Tools to define the callback so that
* it passes through here.
*/
function swftools_admin() {
// Clear caches
cache_clear_all();
cache_clear_all('*', 'cache_filter', TRUE);
if ($page = arg(3)) {
return drupal_get_form('swftools_admin_'. $page .'_form');
}
else {
return system_admin_menu_block_page();
}
}
/**
* Implementation of hook_perm().
*/
function swftools_perm() {
return array('administer flash');
}
function swftools_admin_embed_form() {
include_once(drupal_get_path('module', 'swftools') .'/swftools.admin.inc');
$form = _swftools_admin_embed_form();
// Clear caches
cache_clear_all();
cache_clear_all('*', 'cache_filter', TRUE);
return system_settings_form($form);
}
function swftools_admin_handling_form() {
include_once(drupal_get_path('module', 'swftools') .'/swftools.admin.inc');
$form = _swftools_admin_handling_form();
// Clear caches
cache_clear_all();
cache_clear_all('*', 'cache_filter', TRUE);
return system_settings_form($form);
}
/**
* Output a playlist via a flash file. Note that $playlist_data has a specific
* format that will be documented later.
* @param $playlist_data
*
* Not the name of an xml file!
*
*/
function swf_list($playlist_data, $params = SWFDEFAULT, $flashvars = SWFDEFAULT, $othervars = SWFDEFAULT, $methods = SWFDEFAULT) {
if (is_array($playlist_data)) {
if (!$methods) {
$methods = array();
}
$methods['action'] = $playlist_data['action'];
if (!$othervars) {
$othervars = array();
}
$othervars['playlist_data'] = $playlist_data;
if (isset($playlist_data['filename'])) {
$playlist = $playlist_data['filename'];
}
else {
$playlist = '';
}
return swf($playlist, $params, $flashvars, $othervars, $methods);
}
else {
// Need to verify the direct xml file method before permitting it.
}
}
/**
* Return output, which might be embed markup, or pre-flash markup
* that includes the appropriate jQuery added to the
*
* @param $file
* The file to be played. If it is a SWF file it will usually be embedded directly.
* Use a full URL, a path relative to webroot, or a path relative to the configured files directory.
* @param $params
* An associative array of variables to set.eg. array('bgcolor'=>'FF00FF')
* To set height and width: array('width'=>'200', 'height'=>'120'). However,
* as a convenient alternative for the common requirement of just height and width
* you can also pass a text string like '200x100'.
* If you pass nothing, and the file to play is a .swf, swftools will try and
* establish a natural width and height from the actual .swf file that you've
* passed into $file.
* @param $flashvars
* An associative array of flashvar variables to set. eg. array('playlist'=>'files/my_playlist.xml')
* @param $othervars
* An associative array of variables that might be required by the $player or $embed technique.
* These values are not output as params or flashvars.
* @param $method
* Explicitly declare an action, player or action by passing an array of
* the form: array('action'=>'dosomething','player'=>'withsomething','embed'=>'withthisjavascript').
* These usually default to the administration settings and also you will
* usually use a CONSTANT which will be documented further at a later stage.
*/
function swf($file, $params = SWFDEFAULT, $flashvars = SWFDEFAULT, $othervars = SWFDEFAULT, $methods = SWFDEFAULT) {
// Get all the actions, tools and embedding options available to us.
$all_methods = swftools_methods_available();
// ACTION
// Explicit action on the $methods parameter?
$action = (isset($methods['action'])) ? $methods['action'] : FALSE;
if (!$action) {
// Still no action?
$action = swftools_get_action($file);
}
// HTML ALTERNATIVE
// Get the html which will be used in case flash cannot be displayed.
$html_alt = ($othervars['html_alt']) ? $othervars['html_alt'] : variable_get('swftools_html_alt', 'Sorry, flash is not available.
');
// 'resolved' refers to the fact that these are the methods we
// intend to use, not /all/ methods available.
$resolved_methods = new stdClass();
// PLAYER
// Explicit player on the $methods parameter?
$player = (isset($methods['player'])) ? $methods['player'] : FALSE;
if (!$player) {
// Still no player?
$player = swftools_get_player($action);
if (!$player) {
drupal_set_message("No player is configured for the action '$action'", 'error');
// We pass back the alternative html to be displayed as is.
return $html_alt;
}
}
// Assign the player info.
if (isset($all_methods[$action][$player])) {
$resolved_methods->player = $all_methods[$action][$player];
}
else {
if ($action == SWFTOOLS_SWF_DISPLAY_DIRECT) {
// We seem to have a custom player. We make the method custom and assign the player.
$resolved_methods->player = $all_methods[$action][SWFTOOLS_CUSTOM];
$resolved_methods->player['shared_file'] = $player; // Don't check existence of player file.
}
else {
// All else fails ...
drupal_set_message("Could not find the '$player' file for embedding.", 'error');
return $html_alt;
}
}
// EMBED
// Explicit embed strategy on the $methods parameter?
$embed = (isset($methods['embed'])) ? $methods['embed'] : FALSE;
if (!$embed) {
// Still not sure?
$embed = variable_get(SWFTOOLS_EMBED_METHOD, SWFTOOLS_NOJAVASCRIPT);
}
// Assign the embed info.
$resolved_methods->embed = $all_methods[SWFTOOLS_EMBED_METHOD][$embed];
// Put all the variables on a simple object to make internal function calls simpler.
$vars = new stdClass();
// OTHERVARS
$vars->othervars = (is_array($othervars)) ? $othervars : array();
// PARAMS
// params could be an associative array, or in 'WIDTHxHEIGHT' format.
if ($params) {
if (is_array($params)) {
$vars->params = $params;
}
else {
$dimensions = explode('x', $params);
if (count($dimensions) == 2) {
$vars->params = array('width' => $dimensions[0], 'height' => $dimensions[1]);
}
}
}
else {
$vars->params = array();
}
// FLASHVARS
// flashvars could be an associative array, or in 'a=1&b=2' format.
if ($flashvars) {
if (is_array($flashvars)) {
$vars->flashvars = $flashvars;
}
else {
// Parse the string as if in 'a=1&b=2' format.
parse_str($flashvars, $vars->flashvars);
}
}
else {
$vars->flashvars = array();
}
// BASE
// Determine a reasonable 'base' directory, if it's not already an explicitly declared and valid url.
$base = ($vars->params['base']) ? $vars->params['base'] : '';
if (!$base || !valid_url($base)) {
//$base = swftools_get_media_url(swftools_get_media_path(), FALSE);
$base = swftools_get_media_url('', FALSE);
}
$vars->params['base'] = $base;
// PLAYLIST
if (isset($othervars['playlist_data'])) {
// Generate a playlist and receive a file path in return.
// This file name will be relative webroot
$playlist = TRUE; // Flag it's a playlist.
$file = swftools_generate_playlist($othervars['playlist_data'], $playlist_name, $resolved_methods, $vars, FALSE);
if (!$file) {
drupal_set_message("Unable to create playlist.");
return $html_alt;
}
}
$nocache = '';
if (variable_get('swftools_playlist_caching', 'here') == 'always') {
// Not currently working. Sometimes you may see xml caching.
// $nocache = '?nc='. time();
}
$orig_file = file_create_path($file);
// FILE
// Process the file if not already.
if (!valid_url($file, TRUE)) {
// Get full file path to the webroot.
if (!$playlist) {
$file = swftools_get_media_path() ."/$file" . $nocache;
}
$file_url = swftools_get_media_url($file) . $nocache;
if (!$file_url) {
// Local file didn't exist.
return $html_alt;
}
}
else {
$file_url = $file;
}
// Attach file_url to othervars so player modules have access if required
$vars->othervars['file_url'] = $file_url;
// Determine the "src" attribute of the embed (also applies to the 'movie' attribute).
// Usually this is the Flash Player, but it can also be a swf file, or a custom file
// passed on othervars['shared_file'].
switch ($player) {
case SWFTOOLS_SWF:
// The original file is the src file.
$vars->params['src_path'] = $orig_file;
$vars->params['src'] = $file_url;
break;
case SWFTOOLS_CUSTOM:
$vars->params['src_path'] = $resolved_methods->player['shared_file']; // May need the local path for dimensions.
$vars->params['src'] = swftools_get_media_url($resolved_methods->player['shared_file']);
break;
default:
$vars->params['src_path'] = swftools_get_player_path() .'/'. $resolved_methods->player['shared_file'];
$vars->params['src'] = $GLOBALS['base_url'] .'/'. swftools_get_player_path() .'/'. $resolved_methods->player['shared_file'];
}
// Merge default and user defined "params".
$vars->params = array_merge(_swftools_params(), $vars->params);
// Ask the module implementing the player what flashvars are required, pass
// all existing values by reference to allow optional override at the player.module level.
$player_flashvars = call_user_func_array($resolved_methods->player['module'] .'_swftools_flashvars', array($action, &$resolved_methods, &$vars));
$vars->flashvars = array_merge($vars->flashvars, $player_flashvars);
// Apply the values as requested by the player.module (if applicable).
if (isset($resolved_methods->player['file'])) {
$vars->flashvars[$resolved_methods->player['file']] = $file_url;
}
if (isset($resolved_methods->player['version'])) {
$vars->params['version'] = $resolved_methods->player['version'];
}
// Not a pretty piece of code, but should be ok for the moment. We are
// purposefully passing the width and height
// if we have them. Unsure if this will cause problems with some players.
// It's an ugly piece of code, but will remain in this form until a clearer
// solution arises.
//
// It may be that, in hook_swftools_methods, the flash player indicates that
// it *want* certain values copied b/t params and flashvars.
//
if (!$vars->flashvars['width'] && !$vars->flashvars['height']) {
if ($vars->params['width'] && $vars->params['height']) {
$vars->flashvars['width'] = $vars->params['width'];
$vars->flashvars['height'] = $vars->params['height'];
}
}
if (!$vars->params['width'] && !$vars->params['height']) {
if ($vars->flashvars['width'] && $vars->flashvars['height']) {
$vars->params['width'] = $vars->flashvars['width'];
$vars->params['height'] = $vars->flashvars['height'];
}
}
// If still empty, we try and get them from the file to be embedded.
if (empty($vars->params['height']) && empty($vars->params['width'])) {
$info = swftools_get_info($vars->params['src_path']);
if ($info) {
$vars->params['height'] = $info['height'];
$vars->params['width'] = $info['width'];
};
}
// Build a string out of the flashvars array.
$vars->params['flashvars'] = _swftools_get_flashvars_string($vars->flashvars);
// Call the embedding code to get the html and set the javascript if necessary.
$output = module_invoke($resolved_methods->embed['module'], 'swftools_embed', $action, $resolved_methods, $vars, $html_alt);
// The $html code is already built, but allow it to be changed.
return theme('swftools_embed', $output, $action, $resolved_methods, $vars, $preview);
}
function theme_swftools_embed($embed_code, $action, $methods, $vars, $html_alt) {
// Generate a css id if possible.
$id = ($vars->othervars['id']) ? ' id="swf-'. $vars->othervars['id'] .'"' : '';
$classes[] = 'swftools-wrapper';
$classes[] = str_replace('_', '-', $methods->player['name']);
$classes[] = $vars->othervars['class'];
return ''. $embed_code .'
';
}
/**
* Implementation of swftools_embed hook
* Returns the markup for the page.
*
*/
function swftools_swftools_embed($action = 'add_js', $methods = FALSE, $vars = FALSE, $preview = 'NA') {
if ($action == 'add_js') {
// No javascript stuff for this embed method to do.
return;
}
$P = $vars->params; // For legibility.
$width_attr = ($P['width']) ? ' width="'. $P['width'] .'"' : '';
$height_attr = ($P['height']) ? ' height="'. $P['height'] .'"' : '';
$loop = _swftools_tf($P['loop']);
$menu = _swftools_tf($P['menu']);
$play = _swftools_tf($P['play']);
$fullscreen = _swftools_tf($P['allowfullscreen']);
$id = ($vars->othervars['id']) ? ''."\n" : '';
$name = ($vars->othervars['id']) ? ' name="'. $vars->othervars['id'] .'"' : '';
$swliveconnect = ($P['swliveconnect']) ? ' swliveconnect="'. $P['swliveconnect'] .'"' : '';
$html = ''."\n" ;
return $html;
}
/**
* Collect information from all modules about the Flash players, tools and scripts
* available for various actions.
*
*/
function swftools_methods_available($action = NULL, $reset = FALSE) {
// Cache methods array.
static $methods = array();
if ($reset) {
$methods = array();
}
elseif (count($methods)) {
return ($action) ? $methods[$action] : $methods;
}
// Gather methods.
foreach (module_implements('swftools_methods') AS $mod) {
$methods = array_merge_recursive($methods, call_user_func($mod .'_swftools_methods'));
}
$methods = array_merge_recursive($methods, genericplayers_swftools_methods());
// This module implements a default plain HTML embedding method called 'direct'
$methods[SWFTOOLS_EMBED_METHOD][SWFTOOLS_NOJAVASCRIPT] = array(
'name' => SWFTOOLS_NOJAVASCRIPT,
'module' => 'swftools',
'shared_file' => '',
'title' => t('Embed Flash Directly, don\'t use JavaScript replacement.'),
);
// This module implements swf embedding
$methods[SWFTOOLS_SWF_DISPLAY_DIRECT][SWFTOOLS_SWF] = array(
'name' => SWFTOOLS_SWF,
'module' => 'swftools',
'shared_file' => '',
'title' => t('Use SWF file directly, no streaming through another SWF.'),
);
$methods[SWFTOOLS_SWF_DISPLAY_DIRECT][SWFTOOLS_CUSTOM] = array(
'name' => SWFTOOLS_CUSTOM,
'module' => 'swftools',
'shared_file' => '', // Assigned later.
'title' => t('Use custom SWF file.'),
);
return ($action) ? $methods[$action] : $methods;
}
function swftools_json_params(&$params, $attr = 'swftools') {
return $attr ."='". drupal_to_js($params) ."'";
}
/**
* Implementation of swftools_flashvars hook
* For a random swf file there are no vars to add.
*/
function swftools_swftools_flashvars($action, &$methods, &$vars) {
return $vars->flashvars;
}
/**
* Returns 'true' or 'false' for javascript based on 0,1,TRUE,FALSE etc
*/
function _swftools_tf($bool) {
// String 'false' is treated as TRUE in PHP logic, so force to FALSE
if (strtolower($bool) == 'false') {
$bool = FALSE;
}
// Return 'true' or 'false' now we are sure of result
return $bool ? 'true' : 'false';
}
/**
* Identify the best action based on the file type that is passed
*/
function swftools_get_action($file) {
// Try to determine the action based on the file extension.
$path_parts = pathinfo($file);
switch (strtolower($path_parts['extension'])) {
case 'flv':
return SWFTOOLS_FLV_DISPLAY;
case 'swf':
return SWFTOOLS_SWF_DISPLAY_DIRECT;
case 'mp3':
return SWFTOOLS_MP3_DISPLAY;
case 'jpg': case 'gif': case 'png': case 'jpeg': case 'img':
return SWFTOOLS_IMAGE_DISPLAY_LIST;
default:
// Make a broad assumption that the configured mediaplayer will handle
// this file or playlist.
return SWFTOOLS_MEDIA_DISPLAY_LIST;
}
}
/**
* Identify the best flash player based on the chosen action.
* In a couple of cases we have a built-in default, but FALSE indicates
* that no default player is configured.
*/
function swftools_get_player($action, $part = FALSE) {
$methods = swftools_methods_available($action);
switch ($action) {
case SWFTOOLS_FLV_DISPLAY:
return variable_get(SWFTOOLS_FLV_DISPLAY, GENERIC_FLV);
case SWFTOOLS_MP3_DISPLAY:
return variable_get(SWFTOOLS_MP3_DISPLAY, GENERIC_MP3);
case SWFTOOLS_SWF_DISPLAY_DIRECT:
return variable_get(SWFTOOLS_SWF_DISPLAY_DIRECT, SWFTOOLS_SWF);
default:
return variable_get($action, FALSE);
}
}
/**
* Returns the playlist path relative to webroot.
* This path needs to be writeable, so it is fitting to limit valid
* locations to the files directory.
*
*/
function swftools_get_playlist_path($dir = FALSE) {
if (!$dir) {
$dir = variable_get('swftools_playlist_path', SWFTOOLS_PLAYLIST_PATH);
}
$dir = file_create_path($dir);
// Create playlist directory if necessary
if (!file_check_directory($dir, FILE_CREATE_DIRECTORY)) {
drupal_set_message("$dir does not exist, or is not writeable.");
}
return $dir;
}
/**
* Returns a flash player path relative to webroot. The default value is
* in the modules/swftools/shared directory.
* It may suit some sites to store flash players in an alternative location, but
* the assumption is the location will be on the same server.
* If the path starts with '/', then we can assume is relative to the webroot.
* Otherwise we assume it's in the files directory.
*
*/
function swftools_get_player_path($dir = FALSE) {
if (!$dir) {
$dir = variable_get('swftools_player_path', SWFTOOLS_PLAYER_PATH);
if (!$dir) {
$dir = drupal_get_path('module', 'swftools') .'/shared';
}
}
elseif (substr($dir, 0, 1) == '/') {
$dir = ltrim($dir, '/');
}
else {
$dir = file_create_path($dir);
}
return $dir;
}
/**
* Returns the media path relative to webroot.
* There is a setting 'swftools_media_url', if this is set, we assume the
* media is on a different server, and we don't change the path or check for the
* existence of the media.
* Otherwise we assume the path is inside the files directory.
*
*/
function swftools_get_media_path() {
$url = trim(variable_get('swftools_media_url', ''));
if (!$url || $url == '') {
return file_create_path('');
}
// A remote server is set, so we do not know anything about
// the path between the base url and the file.
return '';
}
/**
* Resolved a path to a full url. The path must be relative to the webroot.
* We check for the existence if a file is the follow is true:
* - swftools_media_url is empty, and hence the local server is assumed.
* - $is_file is TRUE. (You can set this to FALSE if you know the check will fail, like a dynamic playlist.)
* - swftools_check_media is TRUE
*
*/
function swftools_get_media_url($path, $is_file = TRUE) {
$media_url = variable_get('swftools_media_url', '');
if ($media_url) {
// We do nothing with a remote media file.
return "$media_url/$path";
}
if (variable_get('swftools_check_media', TRUE) && $is_file) {
if (file_exists($path)) {
//return $GLOBALS['base_url'] .'/'. $path;
return file_create_url($path);
}
else {
drupal_set_message("Could not display the flash because \"$path\" does not appear to exist.", 'error');
return FALSE;
}
}
else {
//return $GLOBALS['base_url'] .'/'. $path;
return file_create_url($path);
}
}
/**
* "flashvars" is a parameter like height and width, which are
* passed into the flash player as a=1&b=2&...
*
*/
function _swftools_get_flashvars_string(&$flashvars) {
foreach ($flashvars AS $var => $value) {
$flashvars[$var] = str_replace(array('&', '=', '?'), array('%26', '%3D', '%3F'), $value);
}
$encoded = drupal_query_string_encode($flashvars);
// '#' seems to encode as %2523, reverse this, using a more robust hex prefix..
$encoded = str_replace('%2523', '0x', $encoded);
// Fix encoding of :// as per #181998#comment-882293
$encoded = str_replace('%3A', ':', $encoded);
$encoded = str_replace('%252F', '/', $encoded);
return $encoded;
}
/**
* These are the default params.
*
*/
function _swftools_params() {
$swf_options = _swftools_options();
$defaults = array(
'wmode' => variable_get('swftools_params_wmode', 'opaque'),
'bgcolor' => variable_get('swftools_params_bgcolor', '#FFFFFF'),
'menu' => variable_get('swftools_params_menu', FALSE),
'play' => variable_get('swftools_params_play', TRUE),
'loop' => variable_get('swftools_params_loop', FALSE),
'quality' => variable_get('swftools_params_quality', 'autohigh'),
'align' => variable_get('swftools_params_align', 'l'),
'salign' => variable_get('swftools_params_salign', 'tl'),
'scale' => variable_get('swftools_params_scale', 'showall'),
'swliveconnect' => variable_get('swftools_params_swliveconnect', 'default'),
'version' => variable_get('swftools_params_version', '7'),
'allowfullscreen' => variable_get('swftools_params_allowfullscreen', TRUE),
);
$defaults['play'] = _swftools_tf($defaults['play']);
$defaults['loop'] = _swftools_tf($defaults['loop']);
$defaults['menu'] = _swftools_tf($defaults['menu']);
$defaults['allowfullscreen'] = _swftools_tf($defaults['allowfullscreen']);
return $defaults;
}
/**
* flashvar and param option arrays. These are used for options settings in the
* configuration screen and also as a lookup (particularly 'bool') to output the correct value for to html.
*
*/
function _swftools_options() {
// cache output each request
static $swf_options = array();
if (!count($swf_options)) {
$swf_options['quality'] = array('low' => 'low', 'autolow' => 'autolow', 'medium' => 'medium', 'high' => 'high', 'autohigh' => 'autohigh', 'best' => 'best', );
$swf_options['wmode'] = array('window' => 'window', 'opaque' => 'opaque', 'transparent' => 'transparent', );
$swf_options['scale'] = array('showall' => 'showall', 'noborder' => 'noborder', 'exactfit' => 'exactfit', );
$swf_options['align'] = array('default' => 'centered', 'l' => 'left', 'r' => 'right', 't' => 'top', 'b' => 'bottom', );
$swf_options['salign'] = array('l' => 'left', 'r' => 'right', 't' => 'top', 'b' => 'bottom', 'tl' => 'top left', 'tr' => 'top right', 'bl' => 'bottom left', 'br' => 'bottom right', );
$swf_options['bool'] = array('default' => 'default', 'true' => 'true', 'false' => 'false');
}
return $swf_options;
}
/**
* Attempt to return information for the specified file
* Supply the path to the file to be processed, and it return FALSE if no data
* was obtained. The return variable, if successful, is an array that may
* include width, height, extension, file_size, mime_type.
*
*/
function swftools_get_info($file) {
// Only check the file if it is local.
if (variable_get('swftools_media_url', '') == '') {
$info = image_get_info($file);
return $info;
}
return FALSE;
}
/**
* Saves a playlist/xml file to a directory ready for the browser callback.
* Data must be formatted correctly, see docs (link to come)
*
*/
function swftools_generate_playlist(&$playlist_data, $playlist_name, &$method, &$vars) {
// It pays to pass your own filename, if possible, to avoid too much md5 hashing.
if (!$playlist_name) {
$prename = '';
foreach ($playlist_data['playlist'] AS $data) {
$prename .= $data['filename'];
}
$playlist_name = md5($method->player['name'] . $prename) .'.xml';
}
$playlist_name = swftools_get_playlist_path() ."/$playlist_name";
if (variable_get('swftools_playlist_caching', 'here') == 'always') {
// Settings dictate we should always overwrite the playlist.
file_delete($playlist_name);
}
elseif (is_file($playlist_name)) {
return $playlist_name;
}
// Get the playlist/xml formatted to the player's taste.
$func = 'swftools_'. $method->player['name'] .'_playlist';
if (function_exists($func)) {
$playlist = call_user_func($func, $playlist_data, $method, $vars);
}
else {
drupal_set_message('Error with xml generation by the '. $method->player['name'] .' module.', 'error');
}
// Open file.
if (!$handle = fopen($playlist_name, 'a')) {
drupal_set_message("An error occurred trying to create file $playlist_name");
return FALSE;
}
// And write to the file.
if (fwrite($handle, $playlist) === FALSE) {
drupal_set_message("An error occurred trying to create file $playlist_name");
return FALSE;
}
fclose($handle);
return $playlist_name;
}
function swftools_push_js($embed = SWFDEFAULT) {
$all_methods = swftools_methods_available();
if (!$embed) {
$embed = variable_get(SWFTOOLS_EMBED_METHOD, SWFTOOLS_NOJAVASCRIPT);
}
$embed = $all_methods[SWFTOOLS_EMBED_METHOD][$embed];
// Call the module responsible to output the js. Don't pass any additional
// parameters - as we don't want the module to try and return the in-body
// html placeholder for the flash content.
$output = module_invoke($embed['module'], 'swftools_embed');
}
/**
* This function is a work in progress.
*
* Sent through array of files (simple), or an
* If $action is missing then we try to work it out.
*
*/
function swftools_prepare_playlist_data($files, $title = '', $get_action = TRUE, $type_filter = array()) {
$playlist_data = array();
$playlist_data['header']['title'] = $title;
// Run through all $files and and make the data look the same.
$id = 0;
foreach ($files AS $key => $data) {
while (array_key_exists($id, $files)) {
$id++;
}
if (is_object($data)) {
$files[$key] = (array)$data;
}
elseif (!is_array($data)) {
// Move this file name to a new key to give it the structure of a file attachment array
$files[$id]['filepath'] = $data;
if (!is_numeric($key)) {
$files[$id]['filename'] = $key;
}
else {
$files[$id]['filename'] = $data;
}
unset($files[$key]);
}
}
// Check the fileurl element and add generate it if it's missing.
$playlist_data['playlist'] = $files;
foreach ($files AS $key => $data) {
if (!isset($data['fileurl'])) {
if (valid_url($data['filepath'], TRUE)) {
// A full http:// file path has been passed.
$playlist_data['playlist'][$key]['filepath'] = FALSE; // Flag that we don't know the server path.
$playlist_data['playlist'][$key]['fileurl'] = $data['filepath'];
}
elseif (isset($data['fid'])) {
// This is a classes upload module files array.
$playlist_data['playlist'][$key]['filename'] = $data['filename'];
$playlist_data['playlist'][$key]['fileurl'] = swftools_get_media_url($playlist_data['playlist'][$key]['filepath'], FALSE);
}
else {
// Otherwise just complete url path.
$playlist_data['playlist'][$key]['filename'] = $data['filename'];
$playlist_data['playlist'][$key]['filepath'] = swftools_get_media_path() .'/'. $data['filepath'];
$playlist_data['playlist'][$key]['fileurl'] = swftools_get_media_url($playlist_data['playlist'][$key]['filepath']);
}
}
if (!isset($data['filename'])) {
$path_parts = pathinfo($playlist_data['playlist'][$key]['fileurl']);
$playlist_data['playlist'][$key]['filename'] = $path_parts['basename'];
}
if (!isset($data['title'])) {
$playlist_data['playlist'][$key]['title'] = $playlist_data['playlist'][$key]['filename'];
}
// Here is where you might call audio.module or video.module for more.
}
// Note, we want to exit quickly if the caller did not want us to
// dynamically determine the display action by passing $action = FALSE.
if (!$get_action) {
// The caller knows what swftools action to set, so exit here.
return $playlist_data;
}
else {
// Try to work out the action from the files passed.
$first_valid_file_type = FALSE;
$mixed_media = FALSE;
$fids = array();
// Process the files attached to the node to determine the correct action.
foreach ($playlist_data['playlist'] AS $key => $data) {
$path_parts = pathinfo($data['filepath']);
$extension = strtolower($path_parts['extension']);
if (strpos('|jpg|jpeg|gif|png|', $extension)) {
// Treat all types of images as the same file type.
$extension = 'img';
}
// Only process the file if $type_filter is empty (ie. no filter)
// or if the extension is declared in the $file_types array.
if (!count($type_filter) || in_array($extension, $type_filter)) {
// $first_valid_file_type stores the file type of the first valid file.
// This will be compared to subsequent files and if two files
// have different types, the action will be defined as SWFTOOLS_MEDIA_DISPLAY_LIST
// in order to utilize a flexible media player.
if (!$first_valid_file_type) {
$first_valid_file_type = $extension;
}
else {
if ($first_valid_file_type != $extension) {
$mixed_media = TRUE;
}
}
}
else {
// this file is not desired. squash it.
unset($playlist_data['playlist'][$key]);
}
}
// Make a decision based on analysing the file array.
if ($first_valid_file_type == '') {
// No files passed our test.
return FALSE;
}
// Determine the required action.
if ($mixed_media) {
// We have files of multiple types.
$action = SWFTOOLS_MEDIA_DISPLAY_LIST;
}
else {
// We only had one file type, so make up a pretend file name based on
// the discovered file type and find out the default action for this file type.
$action = swftools_get_action('dummy.'. $first_valid_file_type);
}
// Pluralize the action if multiple files, and if not already pluralized.
if (count($playlist_data['playlist']) > 1 && substr($action, -5, 5) != '_list') {
$action = $action .'_list';
}
// Assign the action we've derived.
$playlist_data['action'] = $action;
return $playlist_data;
}
}
/**
* Next three filter related code ported from flash_filter.
*
*/
/*
* Implementation of hook_filter_tips
*
*/
function swftools_filter_tips($delta, $format, $long = false) {
if ($long) {
return t('
Flash Filter
The basic syntax for embedding a flash file (.swf), flash movie (.flv) or audio file (.mp3) is:
[flash:filename.swf]
If you would like to override SWF Tools and flash player default settings,
you can specify additional parameters. For example:
Flash Filter will accept following parameters:
- params : You can specify values for output inside <param>
tags with the <embed> html. Typical values are
bgcolor and wmode. Example:
params="wmode=true&&bgcolor=#00FF00"
- flashvars : You can specify values for output as flashvars, which
become available to the flash player. Refer to the
documentation of the flash player you are using to
know what flashvar options are available.
Example:
flashvars="autostart=true&&volume=80"
- files : Optional list of files to be passed, you\'ll normally define
files relative to your Drupal files directory.
Example:
files="name1=image.jpg&&name2=movie.flv"
- methods : Optional information about how to display the file. The most
common usage is to specify a particular media player and
thus override the settings page.
Example:
methods="player=onepixelout_mp3"
WARNING: with params, flashvars and othervars, pass multiple values
separated by &&.
');
}
else {
return t('You may use !flash_filter_help to display Flash files inline', array("!flash_filter_help" => l('', "filter/tips/$format", NULL, 'filter-flash_filter')));
}
}
/*
* Implementation of hook_filter
*
*/
function swftools_filter($op, $delta = 0, $format = -1, $text = '') {
switch ($op) {
case 'list':
return array(0 => t('SWF Tools Filter'));
case 'no cache':
return FALSE;
case 'description':
return t('Substitutes or with embedding code.');
case 'prepare':
// replace with [swf ] to prevent other filters stripping
return (preg_replace('/\<(swflist|swf)\s*(.*)>/sU', '[\1 \2]', $text));
case 'process':
return _swftools_filter_process_text($text);
default:
return $text;
}
}
/*
* This function processes the filter text that the user has added to the text area.
*
* NOTE to those who know REGULAR EXPRESSIONS ;)
* - I need a better regular expression part for ([\w+\-\\\(\)\/\.]+) which
* should match a file name, file path, file url. At the moment this expression
* is a bit ugly and doesn't match spaces, among other things I guess.
* - Can't seem to match newline chars between the additional variables.
*/
function _swftools_filter_process_text($text) {
$endl = chr(13) ;
if (preg_match_all('@(?:)?\[(swflist|swf)\s*?(.*?)\](?:
)?@s', $text, $match)) {
// $match[0][#] .... fully matched string
// $match[1][#] .... matched tag type ( swf | swflist )
// $match[2][#] .... full params string until the closing '>'
$swftools_parameters = array('file', 'params', 'flashvars', 'othervars', 'methods', 'files');
$match_vars = array();
foreach ($match[2] as $key => $passed_parameters) {
preg_match_all('/\s+?(\w*)=[\"](.*?)[\"]#?/', $passed_parameters, $match_vars[$key]);
// $match_vars[0][#] .... fully matched string
// $match_vars[1][#] .... matched parameter, eg flashvars, params
// $match_vars[2][#] .... value after the '='
// Process the parameters onto the $prepared array.
// Search for standard parameters, parse the values out onto the array.
foreach ($match_vars[$key][1] as $vars_key => $vars_name) {
if ($vars_name == 'file') {
$prepared[$key][$vars_name] = $match_vars[$key][2][$vars_key];
unset ($match_vars[$key][1][$vars_key]);
}
elseif (in_array($vars_name, $swftools_parameters)) {
$prepared[$key][$vars_name] = swftools_url_parse(str_replace(array('&&', '&&'), '&', $match_vars[$key][2][$vars_key]));
unset ($match_vars[$key][1][$vars_key]);
}
}
// Search for remaining parameters, map them as elements of the standard parameters.
if (isset($prepared[$key]['methods']['player'])) {
$player = strtolower($prepared[$key]['methods']['player']);
}
else {
$player_key = array_search('player', $match_vars[$key][1]);
if ($player_key!==FALSE) {
$player = strtolower($match_vars[$key][2][$player_key]);
}
else {
$player = FALSE;
}
}
$prepared[$key]['methods']['player'] = $player;
if (count($match_vars[$key][1])) {
// Find out if a player has been set.
foreach ($match_vars[$key][1] as $vars_key => $vars_name) {
if ($parent = swftools_get_filter_alias($vars_name, $player)) {
if ($parent) {
$prepared[$key][$parent][$vars_name] = $match_vars[$key][2][$vars_key];
}
}
}
}
// Just assigning parameters as false if not already set on the $prepared array.
// Really just to avoid declaration warnings when we call swf and swf_list
if (count($prepared[$key])) {
foreach ($swftools_parameters AS $swfparameter) {
if (!isset($prepared[$key][$swfparameter])) {
$prepared[$key][$swfparameter] = FALSE;
}
}
}
switch ($match[1][$key]) {
case 'swf':
$replace = swf($prepared[$key]['file'], $prepared[$key]['params'], $prepared[$key]['flashvars'], $prepared[$key]['othervars'], $prepared[$key]['methods']);
break;
case 'swflist':
if ($prepared[$key]['files']) {
foreach ($prepared[$key]['files'] AS $name => $filename) {
if (!$filename) {
$prepared[$key]['files'][$name] = $name;
}
}
$playlist_data = swftools_prepare_playlist_data($prepared[$key]['files']);
$replace = swf_list($playlist_data, $prepared[$key]['params'], $prepared[$key]['flashvars'], $prepared[$key]['othervars'], $prepared[$key]['methods']);
}
else {
$replace = '';
}
break;
}
$matched[] = $match[0][$key];
$rewrite[] = $replace;
}
return str_replace($matched, $rewrite, $text);
}
return $text;
}
/*
* This implements a hook that extends the parameters that can be passed to the filter
* so that myvar="value" can be mapped to flashvars, etc.
*
*/
function swftools_get_filter_alias($var, $player = FALSE) {
static $general_mapping = array();
static $player_mapping = array();
if (!count($general_mapping)) {
// Build up the mapping arrays.
$general_mapping = array(
'action' => 'methods',
'embed' => 'methods',
'width' => 'params',
'height' => 'params',
'bgcolor' => 'params',
);
if (!count($player_mapping)) {
$player_mapping = module_invoke_all('swftools_variable_mapping');
}
$combined = array();
if (count($player_mapping)) {
foreach($player_mapping AS $mapping) {
$combined = array_merge($combined, $mapping);
}
$general_mapping = array_merge($combined, $general_mapping);
}
}
// Return the parent of the variable.
if ($player && isset($player_mapping[$player][$var])) {
return $player_mapping[$player][$var];
}
else {
return (isset($general_mapping[$var])) ? $general_mapping[$var] : FALSE;
}
}
function swftools_url_parse($string) {
$return = array();
$pairs = split("&", $string);
foreach($pairs as $pair) {
$splitpair = split("=", $pair);
if(!$splitpair[1] || array_key_exists($splitpair[0], $return)) {
$return[] = $splitpair[0];
}
else {
$return[$splitpair[0]] = $splitpair[1];
}
}
return $return;
}
/**
* Implementation of hook_file_download
* Allows SWF Tools to work with a private file system that might include files
* upload outside the control of an upload module, e.g. FTP of large video files
* If the file is in the playlists directory then return a valid header.
* If the file is of a supported type, based on extension, then return a valid header.
* Note: if any other module returns -1 for this file then access will be denied
* even if SWF Tools tries to allow it. See hook_file_download for details.
*/
function swftools_file_download($file) {
// See if we have a playlist - SWF Tools can allow access to those since it creates them
$playlist_path = preg_quote(variable_get('swftools_playlist_path', SWFTOOLS_PLAYLIST_PATH));
if (preg_match('/^'.$playlist_path.'/', $file)) {
return array(
'Content-Type: '. $mime_types[$extension],
'Content-Length: '. filesize(file_create_path($file)),
);
}
// If SWF Tools is allowed to grant access then check to see if access will be allowed
if (variable_get('swftools_grant_access_to_private_files', SWFTOOLS_GRANT_ACCESS_TO_PRIVATE_FILES)) {
// Get extension of file in question
$extension = pathinfo($file, PATHINFO_EXTENSION);
// Build an array of types that SWF Tools can react to
$mime_types = array(
'swf' => 'application/x-shockwave-flash',
'flv' => 'application/octet-stream',
'xml' => 'text/xml',
'mp3' => 'audio/mpeg',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
);
// If file is one of the above types, based on the extension, return headers
if ($mime_types[$extension]) {
return array(
'Content-Type: '. $mime_types[$extension],
'Content-Length: '. filesize(file_create_path($file)),
);
}
}
}