? .cvsignore
? browser
? media-popup.patch
? images/icons/tango
? images/icons/tango-icon-theme-0.8.90.tar.gz
Index: media.browser.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/media/media.browser.inc,v
retrieving revision 1.16
diff -u -r1.16 media.browser.inc
--- media.browser.inc	13 Aug 2010 19:12:22 -0000	1.16
+++ media.browser.inc	3 Sep 2010 18:48:03 -0000
@@ -156,8 +156,6 @@
   $plugins = array(
     'upload' => array(
      ),
-    'fromurl' => array(
-     ),
     'library' => array(
      ),
    );
@@ -189,17 +187,6 @@
         ),
       );
       break;
-    case 'fromurl':
-      // @todo: implement the multiselect argument here.
-      $from_url_form = drupal_get_form('media_add_from_url',  $types, $multiselect);
-      return array(
-        '#title' => t('From URL'),
-        'form' => array($from_url_form),
-        '#attached' => array(
-          //'js' => array($path . '/javascript/plugins/media.fromurl.js'),
-        ),
-      );
-      break;
     case 'library':
       return array(
         '#title' => t('Library'),
Index: media.pages.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/media/media.pages.inc,v
retrieving revision 1.23
diff -u -r1.23 media.pages.inc
--- media.pages.inc	14 Aug 2010 01:50:30 -0000	1.23
+++ media.pages.inc	3 Sep 2010 18:48:03 -0000
@@ -158,7 +158,7 @@
   
   // A blank set of allowed file extensions means no need to validate.
   if (!$validators['file_validate_extensions'][0]) {
-    unset($validators['file_validate_extensions']);
+    $validators['file_validate_extensions'] = array(0 => '');
   }
   // Use the PHP limit for filesize if no variable was set.
   if (!$validators['file_validate_size']) {
@@ -170,7 +170,7 @@
   }
 
   $form['#validators'] = $validators;
-
+  
   $form['upload'] = array(
     '#type' => 'file',
     '#title' => t('Upload a new file'),
@@ -192,7 +192,7 @@
 function media_add_upload_validate($form, &$form_state) {
   // Save the file as a temporary file.
   $file = file_save_upload('upload', $form['#validators']);
-
+  
   if ($file === NULL) {
     form_set_error('upload', t("No file appears to have been selected."));
   }
@@ -272,155 +272,6 @@
 }
 
 /**
- *  Callback for /media/add/upload and /admin/content/media/add/upload.
- *  @TODO: work on the description.
- *  @TODO: allow stream wrappers to add to the description.
- *  @see media_media_browser_plugins().
- */
-function media_add_from_url($form, &$form_state = array(), $types = NULL) {
-  $form['url'] = array(
-    '#type' => 'textfield',
-    '#title' => 'URL',
-    '#description' => 'Input any url which Drupal can handle',
-    '#attributes' => array('class' => array('media-add-from-url')),
-  );
-  
-  $form['preview'] = array(
-    '#type' => 'item',
-    '#title' => t('Preview'),
-    '#markup' => '<div id="media-add-from-url-preview"></div>'
-  );
-
-  $form['submit'] = array(
-    '#type' => 'submit',
-    '#value' => 'Submit',
-  );
-
-  $form['#validators'] = array();
-  if ($types) {
-    $form['#validators']['media_file_validate_types'] = array($types);
-  }
-
-  // Add the javascript for live previews on textfield change.
-  $form['#attached'] = array(
-    'js' => array(drupal_get_path('module', 'media') . '/javascript/media-add_from_url.js'),
-  );
-
-  $settings = array(
-    'media' => array(
-      'add_from_url_preview' => url('media/js'),
-    ),
-  );
-  drupal_add_js($settings, array('type' => 'setting'));
-
-  return $form;
-}
-
-/**
- *  Allow stream wrappers to have their chance at validation.
- *
- *  Any module that implements hook_media_parse will have an
- *  opportunity to validate this.
- *
- *  @see media_parse_to_uri().
- */
-function media_add_from_url_validate($form, &$form_state) {
-  // Supported Schemes for media:
-  $supported_schemes = media_variable_get('fromurl_supported_schemes');
-  $scheme = file_uri_scheme($form_state['values']['url']);
-  if (!in_array($scheme, $supported_schemes)) {
-    form_set_error('url', t('Invalid URL: Only the following types of urls are supported: @supported_schemes', array('@supported_schemes' => implode(', ', $supported_schemes))));
-    return;
-  }
-  
-  // We have a dry-run of the parsing process to allow specific streams to
-  // catch an error, for instance to inform us that a video is no longer
-  // available or that a specific URL structure is not supported.
-  try {
-    // Returns the URI, or NULL on failure.
-    $uri = media_parse_to_uri($form_state['values']['url']);
-  }
-  catch (Exception $e) {
-    // Pass the error back to the user.
-    form_set_error('url', $e->getMessage());
-    return;
-  }
-
-  // This is just stupid, but I need to validate something here.
-  // @TODO: We really should retreive the file and validate its mime-type here.
-  // This is not a reliable way to get it.
-
-  if (!$uri) {
-    $uri = $form_state['values']['url'];
-  }
-  $validators = $form['#validators'];
-  if ($validators) {
-    $file = file_uri_to_object($uri);
-    // Check for errors. @see media_add_upload_validate calls file_save_upload().
-    // this code is ripped from file_save_upload because we just want the validation part.
-    // Call the validation functions specified by this function's caller.
-    $errors = file_validate($file, $validators);
-    
-    if (!empty($errors)) {
-      $message = t('%url could not be added.', array('%url' => $form_state['values']['url']));
-      if (count($errors) > 1) {
-        $message .= theme('item_list', array('items' => $errors));
-      }
-      else {
-        $message .= ' ' . array_pop($errors);
-      }
-      form_set_error('url', $message);
-      return FALSE;
-    }
-  }
-
-  if (empty($uri)) {
-    // @todo - at the moment we don't actual do any real validation.
-    // form_set_error('url', t('Invalid URL'));
-  }
-  // @TODO: Validate that if we have no $uri that this is a valid file to
-  // save. For instance, we may only be interested in images, and it would
-  // be helpful to let the user know they passed the HTML page containing
-  // the image accidentally. That would also save us from saving the file
-  // in the submit step.
-  
-  // This is kinda a hack of the same.
-
-  // This should use the file_validate routines that the upload form users.
-  // We need to fix the media_parse_to_file routine to allow for a validation.
-}
-
-/**
- *  Upload a file from a URL.
- *
- *  This will copy a file from a remote location and store it locally.
- *  @see media_parse_to_uri().
- *  @see media_parse_to_file().
- */
-function media_add_from_url_submit($form, &$form_state) {
-  $url = $form_state['values']['url'];
-  $uri = ''; // The URI we are eventually saving to the files table
-
-  // Save the remote file
-  // @TODO: We should really separate parsing the URL, retreiving the file
-  // and inserting into different operations.
-  try {
-    $file = media_parse_to_file($url);
-  }
-  catch (Exception $e) {
-    form_set_error('url', $e->getMessage());
-    return;
-  }
-
-  if (!$file->fid) {
-    form_set_error('url', 'Unknown error: unable to add file, please check URL and try again ' . $url);
-    return;
-  }
-
-  $form_state['redirect'] = array('media/browser', array('query' => array('render' => 'media-popup', 'fid' => $file->fid)));
-}
-
-/**
  * Form builder: Builds the edit file form.
  */
 function media_edit($form, $form_state, $media) {
Index: media.types.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/media/media.types.inc,v
retrieving revision 1.11
diff -u -r1.11 media.types.inc
--- media.types.inc	24 Jun 2010 09:39:42 -0000	1.11
+++ media.types.inc	3 Sep 2010 18:48:03 -0000
@@ -247,9 +247,6 @@
   }
 
   if (!empty($args['streams'])) {
-    // @TODO: Write this.
-    // Note that this will ultimately need to be above mimetypes and extensions
-    // so that we can allow for things like flickr photos vs. slideshows, etc.
   }
 }
 
Index: modules/media_internet/media_internet.api.php
===================================================================
RCS file: modules/media_internet/media_internet.api.php
diff -N modules/media_internet/media_internet.api.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/media_internet/media_internet.api.php	3 Sep 2010 18:48:03 -0000
@@ -0,0 +1,22 @@
+<?php
+// $Id$
+
+/**
+ * Implementors return an multidim array, keyed by a class name
+ * with the following elements:
+ *
+ * - title
+ * - logo (optional)
+ * - hidden: bool If the logo should be shown on form. (optional)
+ * - weight (optional)
+ */
+function hook_media_internet_providers() {
+  return array(
+    'youtube' => array(
+      'title' => 'youtube',
+      'logo' => 'youtube.jpg'
+    ),
+  );
+}
+
+?>
\ No newline at end of file
Index: modules/media_internet/media_internet.info
===================================================================
RCS file: modules/media_internet/media_internet.info
diff -N modules/media_internet/media_internet.info
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/media_internet/media_internet.info	3 Sep 2010 18:48:03 -0000
@@ -0,0 +1,9 @@
+; $Id$
+
+name = Media Internet Sources
+description = Provides an API for accessing media on various internet services
+package = Media
+core = 7.x
+php = 5.2
+files[] = media_internet.module
+dependencies[] = media
Index: modules/media_internet/media_internet.module
===================================================================
RCS file: modules/media_internet/media_internet.module
diff -N modules/media_internet/media_internet.module
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/media_internet/media_internet.module	3 Sep 2010 18:48:03 -0000
@@ -0,0 +1,343 @@
+<?php
+//$Id$
+
+/**
+ * Implements hook_media_browser_plugin_info().
+ */
+function media_internet_media_browser_plugin_info() {
+  $plugins = array(
+    /*
+     @todo: Coming soon.
+     'search' => array(
+     ),
+    */
+    'media_internet' => array(
+     ),
+   );
+  return $plugins;
+}
+
+/**
+ * Implements hook_media_browser_plugin_view().
+ */
+function media_internet_media_browser_plugin_view($plugin_name, $params) {
+  $path = drupal_get_path('module', 'media');
+
+  $types = isset($params['types']) ? $params['types'] : array();
+  $multiselect = isset($params['multiselect']) ? $params['multiselect'] : FALSE;
+  
+  $redirect = array('media/browser', array('query' => array('render' => 'media-popup')));
+  switch ($plugin_name) {
+    case 'media_internet':
+      // @todo: implement the multiselect argument here.
+      $from_web_form = drupal_get_form('media_internet_add',  $types, $multiselect);
+      return array(
+        '#title' => t('Web'),
+        'form' => array($from_web_form),
+        '#attached' => array(
+          //'js' => array($path . '/javascript/plugins/media.fromurl.js'),
+        ),
+      );
+      break;
+  }
+  
+  return array();
+}
+ 
+/**
+ *  Provides a form for adding media items from 3rd party sources.
+ */
+function media_internet_add($form, &$form_state = array(), $types = NULL) {
+  $form['embed_code'] = array(
+    '#type' => 'textfield',
+    '#title' => 'URL or Embed code',
+    '#description' => 'Input a url or embed code from one of the listed providers.',
+    '#attributes' => array('class' => array('media-add-from-url')),
+  );
+  
+  
+  // @todo:
+  // Add live previews back (currently broken)
+  
+  //$form['preview'] = array(
+  //  '#type' => 'item',
+  //  '#title' => t('Preview'),
+  //  '#markup' => '<div id="media-add-from-url-preview"></div>'
+  //);
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => 'Submit',
+  );
+
+  $form['#validators'] = array();
+  if ($types) {
+    $form['#validators']['media_file_validate_types'] = array($types);
+  }
+  
+  $form['providers'] = array();
+  $form['providers']['header'] = array('#markup' => '<h2> Supported Providers </h2>');
+  foreach (media_internet_get_providers() as $key => $provider) {
+    if (empty($provider['hidden']) || $provider['hidden'] != TRUE) {
+      $form['providers'][$key] = array('#markup' => $provider['title']);
+    }
+  }
+  if (count($form['providers']) == 1) {
+    // Just the header, no actual providers
+    unset($form['providers']['header']);
+  }
+  
+  return $form;
+}
+
+/**
+ *  Allow stream wrappers to have their chance at validation.
+ *
+ *  Any module that implements hook_media_parse will have an
+ *  opportunity to validate this.
+ *
+ *  @see media_parse_to_uri().
+ */
+function media_internet_add_validate($form, &$form_state) {
+  // Supporting providers can now claim this input.  It might be a URL, but it
+  // might be an embed code as well.
+  $embed_code = $form_state['values']['embed_code'];
+  
+  try {
+    $provider = media_internet_get_provider($embed_code);
+    $provider->validate();  
+  } catch (MediaInternetNoHandlerException $e) {
+    form_set_error('url', $e->getMessage());
+    return;
+  } catch (MediaInternetValidationException $e) {
+    form_set_error('url', $e->getMessage());
+    return;
+  }
+  
+  $validators = $form['#validators'];
+  $file = $provider->getFileObject();
+  if ($validators) {
+    try {
+      $file = $provider->getFileObject();
+    } catch (Exception $e) {
+      form_set_error('url', $e->getMessage());
+      return;
+    }
+    
+    // Check for errors. @see media_add_upload_validate calls file_save_upload().
+    // this code is ripped from file_save_upload because we just want the validation part.
+    // Call the validation functions specified by this function's caller.
+    $errors = file_validate($file, $validators);
+    
+    if (!empty($errors)) {
+      $message = t('%url could not be added.', array('%url' => $embed_code));
+      if (count($errors) > 1) {
+        $message .= theme('item_list', array('items' => $errors));
+      }
+      else {
+        $message .= ' ' . array_pop($errors);
+      }
+      form_set_error('url', $message);
+      return FALSE;
+    }
+  }
+  // @TODO: Validate that if we have no $uri that this is a valid file to
+  // save. For instance, we may only be interested in images, and it would
+  // be helpful to let the user know they passed the HTML page containing
+  // the image accidentally. That would also save us from saving the file
+  // in the submit step.
+  
+  // This is kinda a hack of the same.
+
+  // This should use the file_validate routines that the upload form users.
+  // We need to fix the media_parse_to_file routine to allow for a validation.
+}
+
+/**
+ *  Upload a file from a URL.
+ *
+ *  This will copy a file from a remote location and store it locally.
+ *  @see media_parse_to_uri().
+ *  @see media_parse_to_file().
+ */
+function media_internet_add_submit($form, &$form_state) {
+  $emebed_code = $form_state['values']['embed_code'];
+  try {
+    // Save the remote file
+    $provider = media_internet_get_provider($emebed_code);
+    // Providers decide if they need to save locally or somewhere else.
+    // This method returns a file object
+    $file = $provider->save();
+  }
+  catch (Exception $e) {
+    form_set_error('url', $e->getMessage());
+    return;
+  }
+
+  if (!$file->fid) {
+    form_set_error('url', 'Unknown error: unable to add file, please check URL / Embed code and try again ' . $emebed_code);
+    return;
+  }
+
+  $form_state['redirect'] = array('media/browser', array('query' => array('render' => 'media-popup', 'fid' => $file->fid)));
+}
+
+/**
+ * Gets the list of providers.
+ *
+ * A "Provider" is a bit of meta-data like a title and a logo and a class which
+ * can handle saving remote files.  Each provider is able to parse an embed code or URL
+ * and store it as a file object in file_managed.
+ */
+function media_internet_get_providers() {
+  $providers = &drupal_static(__FUNCTION__, array());
+  if (!$providers) {
+    foreach (module_implements('media_internet_providers') as $module) {
+      foreach (module_invoke($module, 'media_internet_providers') as $key => $provider) {
+        // Store the module here too for convinience.
+        $providers[$key] = $provider;
+        $providers[$key]['module'] = $module;
+        if (!isset($providers[$key]['weight'])) {
+          $providers[$key]['weight'] = 0;
+        }
+      }
+    }
+    uasort($providers, 'drupal_sort_weight');
+  }
+  return $providers;
+}
+
+/**
+ * Finds the appropriate provider for a given URL or embed_string
+ *
+ * Each provider has a claim() method which it uses to tell media_internet
+ * that it should handle this input.  We cycle through all providers to find
+ * the right one.
+ *
+ * @todo: Make this into a normal hook or something because we have to instantiate
+ * each class to test and that's not right.
+ */
+function media_internet_get_provider($embed_string) {
+  foreach(media_internet_get_providers() as $class_name => $nothing) {
+    $p = new $class_name($embed_string);
+    if ($p->claim($embed_string)) {
+      return $p;
+    }
+  }
+  throw new MediaInternetNoHandlerException(t('Unable to handle the provided embed string or URL.'));
+}
+
+/**
+ * Implements hook_media_internet_providers();
+ *
+ * Provides a very basic handler which coppies files from remote sources to the
+ * local files directory.
+ */ 
+function media_internet_media_internet_providers() {
+  return array(
+    'MediaInternetFileHandler' => array(
+      'title' => 'Files',
+      'hidden' => TRUE,
+      // Make it go last.
+      'weight' => 10000,
+    ),
+  );
+}
+
+class MediaInternetFileHandler extends MediaInternetBaseHandler {
+  
+  public $fileObject;
+  
+  public function preSave(&$file_obj) {
+    // Coppies the remote file locally.
+    $remote_uri = $file_obj->uri;
+    $local_uri = file_stream_wrapper_uri_normalize('temporary://' . basename($remote_uri));
+    if (!@copy($remote_uri, $local_uri)) {
+      throw new Exception('Unable to add file ' . $remote_uri);
+      return;
+    }
+    // Make the current fileObject point to the local_uri, not the remote one.
+    $file_obj = file_uri_to_object($local_uri);
+  }
+  
+  public function postSave(&$file_obj) {
+    $scheme = variable_get('file_default_scheme', 'public') . '://';
+    $uri = file_stream_wrapper_uri_normalize($scheme . $this->fileObject->filename);
+    // Now to its new home.
+    $file_obj = file_move($file_obj, $uri, FILE_EXISTS_RENAME);
+  }
+  
+  public function getFileObject() {
+    if (!$this->fileObject) {
+      $this->fileObject = file_uri_to_object($this->embedCode);
+    }
+    return $this->fileObject;
+  }
+  
+  public function claim($embedCode) {
+    $supported_schemes = media_variable_get('fromurl_supported_schemes');
+    $scheme = file_uri_scheme($embedCode);
+    if (in_array($scheme, $supported_schemes)) {
+      return TRUE;
+    }
+  }
+}
+
+/**
+ * 
+ */
+abstract class MediaInternetBaseHandler {
+  
+  public function __construct($embedCode) {
+    $this->embedCode = $embedCode;
+  }
+  
+  /**
+   * If required, implementors can validate the embedCode.
+   */
+  public function validate() {}
+  
+  /**
+   * Returns a file object which can be used for validation
+   *
+   * @return StdClass
+   */
+  abstract public function getFileObject();
+  
+  /**
+   * Saves a file to the file_managed table (with file_save)
+   *
+   * @return StdClass
+   */
+  public function save() {
+    $file_obj = $this->getFileObject();
+    $this->preSave($file_obj);
+    file_save($file_obj);
+    $this->postSave($file_obj);
+    return $file_obj;
+  }
+  
+  /**
+   * After the file has been saved, implementors may do additional operations.
+   * 
+   * @param $file_obj;
+   */
+  public function postSave($file_obj) {
+    
+  }
+  
+  /**
+   * Before the file has been saved, implementors may do additional operations.
+   */
+  public function preSave($file_obj) {
+    
+  }
+}
+
+class MediaInternetValidationException extends Exception {
+  
+}
+
+class MediaInternetNoHandlerException extends Exception {
+  
+}
\ No newline at end of file
