You are here

function _emogrifier_process in Emogrifier 6

Same name and namespace in other branches
  1. 8 emogrifier.module \_emogrifier_process()
  2. 7.2 emogrifier.module \_emogrifier_process()
  3. 7 emogrifier.module \_emogrifier_process()

Returns $text with stylesheet rules converted to inline style attributes.

1 call to _emogrifier_process()
emogrifier_filter in ./emogrifier.module
Implements hook_filter().

File

./emogrifier.module, line 56

Code

function _emogrifier_process($text) {
  if (empty($text)) {
    return '';
  }

  // Avoid PHP fatal errors when the 'dom' extension is not loaded.
  if (!extension_loaded('dom')) {
    watchdog('emogrifier', 'The PHP <a href="!dom">%dom</a> extension required by <a href="!emogrifier">%emogrifier</a> is not loaded.', array(
      '!dom' => url('http://php.net/dom'),
      '%dom' => 'dom',
      '!emogrifier' => url('http://drupal.org/project/emogrifier'),
      '%emogrifier' => 'Emogrifier',
    ), WATCHDOG_WARNING);
    return $text;
  }
  if (!_emogrifier_available()) {
    watchdog('emogrifier', 'The <a href="!library">%emogrifier</a> class library required by the <a href="!module">%emogrifier</a> module could not be loaded.', array(
      '!library' => url('http://www.pelagodesign.com/sidecar/emogrifier/'),
      '%emogrifier' => 'emogrifier',
      '!module' => url('http://drupal.org/project/emogrifier'),
    ), WATCHDOG_WARNING);
    return $text;
  }
  $styles = array();
  $urls = array();

  // Match linked stylesheets.
  if (preg_match_all('#<link[^>]*>\\s*#si', $text, $links)) {
    foreach ($links[0] as $link) {
      if (preg_match('#\\s+type\\s*=\\s*(["\']?)text/css\\1#si', $link) && preg_match('#\\s+rel\\s*=\\s*(["\']?)stylesheet\\1#si', $link) && preg_match('#\\s+media\\s*=\\s*(["\']?)all\\1#si', $link) && preg_match('#\\s+href\\s*=\\s*(["\']?)([^?]*?)(\\?.*?)?\\1#si', $link, $match)) {
        $urls = array_merge($urls, array_slice($match, 2, 1));
      }
      $text = str_replace($link, '', $text);
    }
  }

  // Match style blocks, possibly with @imports.
  if (preg_match_all('#(<style[^>]*>)\\s*(<!--)?\\s*(.*?)\\s*(-->)?\\s*</style>\\s*#si', $text, $blocks)) {
    foreach ($blocks[1] as $block => $tag) {
      if (preg_match('#\\s+type\\s*=\\s*(["\']?)text/css\\1#si', $tag) && preg_match('#\\s+media\\s*=\\s*(["\']?)all\\1#si', $tag)) {
        if (preg_match_all('#@import\\s+url\\s*\\(\\s*(["\']?)([^?]*)(\\?.*?)?\\1\\s*\\)\\s*;#si', $blocks[3][$block], $imports)) {
          $urls = array_merge($urls, $imports[2]);
          $rules = trim(str_replace($imports[0], '', $blocks[3][$block]));
          if (!empty($rules)) {
            $styles[] = $rules;
          }
        }
      }
    }
    $text = str_replace($blocks[0], '', $text);
  }
  foreach ($urls as $url) {
    if (($path = url_to_realpath(check_url($url))) && file_exists($path) && ($style = trim(file_get_contents($path)))) {
      $styles[] = $style;
    }
  }

  // Strip comments and unecessary whitespace from the collected style rules.
  $styles = preg_replace(array(
    '/[[:space:]]+/s',
    '#/\\*.*?\\*/#',
    '/ +/',
  ), ' ', $styles);

  // Remove quote marks around urls.
  $styles = preg_replace('/url[[:space:]]*\\([[:space:]]*(["\'])(.*?)\\1[[:space:]]*\\)/mis', 'url(\\2)', $styles);
  $text = preg_replace('/url[[:space:]]*\\([[:space:]]*(["\'])(.*?)\\1[[:space:]]*\\)/mis', 'url(\\2)', $text);

  // Emogrify can't handle several CSS rules on one line,
  // so insert a newline character after each closing bracket.
  $styles = preg_replace('/}\\s*/', "}\n", implode("\n", $styles));

  // Strip unwanted container tags.
  $text = preg_replace('#<(applet|audio|canvas|embed|frameset|head|iframe|object|ruby|script|style|title|video)[^[:alnum:]].*?</\\1\\s*>\\s*#si', '', '<head>' . $text);

  // Replace or remove other tags.
  $text = preg_replace_callback('#(<(/?))([!\\[[:alnum:]\\]]{2,12})([^>]*>)#s', '_emogrifier_replace_tag', $text);

  // Strip unwanted container tags replaced by comments.
  $text = preg_replace('#<!--.*?-->\\s*#si', '', $text);

  // Load the html text and style rules.
  $emogrifier = new Emogrifier('<html><body>' . $text . '</body></html>', $styles);

  // Apply the rules to create inline style attributes.
  $text = @$emogrifier
    ->emogrify();

  // Extract body portion.
  $text = preg_replace('#.*<body>(.*)</body>.*#Usi', '\\1', $text);

  // Strip unwanted attributes.
  $text = preg_replace(array(
    '#(<[^>]*?)\\s*class\\s*=\\s*(["\']).*?\\2#si',
    '#(<[^>]*?)\\s*id\\s*=\\s*(["\']).*?\\2#si',
  ), '\\1', $text);
  return $text;
}