? 148300_pathfilter_auto_internal.patch
? pathfilter.install
Index: pathfilter.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/pathfilter/pathfilter.module,v
retrieving revision 1.5.2.1.2.7
diff -u -p -r1.5.2.1.2.7 pathfilter.module
--- pathfilter.module	17 May 2009 12:21:56 -0000	1.5.2.1.2.7
+++ pathfilter.module	23 May 2009 21:27:33 -0000
@@ -17,6 +17,7 @@
  * Credits:   
  * @author Ray Zimmerman (drupal.org user "RayZ")
  * @author Tom Kirkpatrick (drupal.org user "mrfelton"), www.kirkdesigns.co.uk
+ * @author George Montana Harkin (auto internalization)
  */
 
 /**
@@ -64,7 +65,6 @@ function pathfilter_filter($op, $delta =
         // returned, once any necessary substitutions have taken place.
         case 'process':
           $patterns = array();
-          $replacement = array();
           $patterns[] = '/(["\'])(internal):([^"#\?\']+)\??([^"#\']+)?#?([^"\']+)?\1/';
           $patterns[] = '/(["\'])(files):([^"\']+)\1/';
           
@@ -134,6 +134,7 @@ function _pathfilter_process_files($matc
   return $matches[1] . file_create_url($matches[3]) . $matches[1];
 }
 
+
 /**
  * Helper settings function for hook_filter('settings').
  */
@@ -152,5 +153,129 @@ function _pathfilter_settings($format) {
     '#default_value' => variable_get('pathfilter_link_absolute_'. $format, 1),
     '#description' => t('Should internal paths be transformed to absolute URLs, such as %absolute_url or absolute paths, like %absolute_path. Note that your changes may not appear until the cache has been cleared.', array('%absolute_url' => 'http://www.example.com/my-page', '%absolute_path' => '/my-page')),
   );
+  $form['pathfilter']['pathfilter_process_all'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Enable automatic url processing for attributes.'),
+    '#default_value' => variable_get('pathfilter_process_all', 0),
+    '#description' => t('When this option is enabled, all %element_list elements will automatically have the servername and base path of their src, href, and action urls replaced with %internal. On editing of these elements, all instances of %internal will be replaced with the site\'s base path (%current_base_path).', array('%element_list' => '<img>, <a>, <script>, <object>, and <form>', '%internal' => '\'internal:\'', '%current_base_path' => base_path())),
+  );
   return $form;
-}
\ No newline at end of file
+}
+
+/**
+ * Implementation of hook_nodeapi().
+ * 
+ * Modifies submitted node body values. Replaces base_path() in images, hrefs, 
+ * etc with 'internal:' on save. When editing a node, the body's 'internal:' 
+ * strings are replaced with 'base_path()'.
+ */
+function pathfilter_nodeapi(&$node, $op ) {
+  switch ($op) {
+    case 'prepare':
+      if (variable_get('pathfilter_process_all', 1)) {
+        $node = (array) $node; //Cast to an array so we can walk it.
+        array_walk_recursive( $node, '_pathfilter_replace_internal' );
+        $node = (object) $node; //Cast it back to an object. Do we lose something here?
+      }
+      break;
+    case 'presave':
+      /* We do more when we look for what to replace with 'internal:'
+      - Only want to replace items that are links, not text or data
+      - Check to see if they specified the hostname of the server 
+      - Make sure to accept items that have multiple slashes.*/
+      if (variable_get('pathfilter_process_all', 1)) {
+        $node = (array) $node; //Cast to an array so we can walk it.
+        array_walk_recursive( $node, '_pathfilter_internalize' );
+        $node = (object) $node; //Cast it back to an object. Do we lose something here?
+      }
+      break;
+  }
+}
+
+
+/**
+ * Replaces the internal: in elements with the url for it
+ */
+function _pathfilter_replace_internal( &$item, $key ){
+  $patterns = array();
+  $patterns[] = '/(["\'])(internal):([^"#\?\']+)\??([^"#\']+)?#?([^"\']+)?\1/';
+  $patterns[] = '/(["\'])(files):([^"\']+)\1/';
+  
+  // use the 'currying' technique to allow us to pass the format into
+  // the callback function.
+  // FIXME: Need to get hold of $format somehow, to find out if links should be
+  // absolute or not. Or do we? Does it really matter if we use absolute or not
+  // for this purpose?
+  $callback = _pathfilter_curry(_pathfilter_process, 2);
+  $new_path = preg_replace_callback($patterns, $callback($format), $item);
+  $item = $new_path;
+}
+
+/**
+ * Internalizes all urls in a item, key 
+ */
+function _pathfilter_internalize(&$item, $key) {
+  // First we find all of the items that look like they need to be replaced.
+  $pattern = '/(<img|<a|<script|<object|<form)[^\>]*>/i';
+  preg_match_all( $pattern, $item, $matches );
+  // Then we do 'internal:' or 'files:' replacement.
+  foreach ( $matches[0] as $match ) {
+    preg_match( '/(src=|href=|action=)(\'|")([^\'"]*)\2[^\>]*>/', $match, $url );
+    
+    $parsed_path = parse_url($url[3]);
+    $relative_path = trim($parsed_path['path'], '/');
+    if (substr(($relative_path), 0, strlen(file_directory_path())) == file_directory_path()) {
+      // Do replacement with 'files:' if needed 
+      $pathfilter_files_re = _pathfilter_files_replacement_re();
+      $internalized_path = preg_replace($pathfilter_files_re, 'files:', $url[3]);
+    }
+    else {
+      // Ensure we have the Drupal system path
+      $system_path = drupal_get_normal_path($relative_path);
+      $system_path = preg_replace('/'.preg_quote($relative_path, '/').'/', $system_path, $url[3]);
+      
+      // Do replacement with 'internal:' if needed 
+      $pathfilter_internal_re = _pathfilter_internal_replacement_re();
+      $internalized_path = preg_replace($pathfilter_internal_re, 'internal:', $system_path);
+    }
+    
+    // Update original string with changes
+    $new_path = preg_replace( '/(src=|href=|action=)(["\'])('.preg_quote($url[3], '/').')\2/', '$1$2'.$internalized_path.'$2', $item );
+    //if ($match != $new_path) dsm('translated: '.$url[3] .' => '.$internalized_path);
+    $item = $new_path;
+  }
+}
+
+/**
+ * Generates the regular expression that will be used to find a url that should
+ * have 'internal:'.
+ */
+function _pathfilter_internal_replacement_re() {
+  static $pathfilter_internal_re;
+
+  if ($pathfilter_internal_re != '') {
+    return $pathfilter_internal_re;
+  }
+
+  global $base_url;
+  $base_path = base_path();
+  $pathfilter_internal_re = '/^('.preg_quote($base_url, '/').')?'.preg_quote($base_path, '/').'/';
+  return $pathfilter_internal_re;
+}
+
+/**
+ * Generates the regular expression that will be used to find a url that should
+ * have 'files:'.
+ */
+function _pathfilter_files_replacement_re() {
+  static $pathfilter_files_re;
+
+  if ($pathfilter_files_re != '') {
+    return $pathfilter_files_re;
+  }
+
+  global $base_url;
+  $base_path = base_path();
+  $pathfilter_files_re = '/^('.preg_quote($base_url, '/').')?'.preg_quote($base_path, '/').preg_quote(file_directory_path().'/', '/').'/';
+  return $pathfilter_files_re;
+}
