You are here

autofloat.module in AutoFloat 6.2

Autofloat module: A filter that floats images left and right automatically.

File

autofloat.module
View source
<?php

/**
 * @file
 * Autofloat module: A filter that floats images left and right automatically.
 */

/**
 * Implements hook_help().
 */
function autofloat_help($path, $arg) {
  switch ($path) {
    case 'admin/help#autofloat':

      // Return a line-break version of the README.txt.
      return _filter_autop(file_get_contents(dirname(__FILE__) . '/README.txt'));
  }
}

/**
 * Implements hook_init().
 */
function autofloat_init() {

  // Determine the setting to use autofloat.css or not.
  if (variable_get('autofloat_css', 1)) {
    drupal_add_css(drupal_get_path('module', 'autofloat') . '/autofloat.css', $type = 'module', $media = 'all', $preprocess = TRUE);
  }
}

/**
 * Implements hook_menu().
 */
function autofloat_menu() {
  $items['admin/settings/autofloat'] = array(
    'title' => 'AutoFloat',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'autofloat_admin_settings',
    ),
    'access arguments' => array(
      'administer filters',
    ),
    'description' => 'Filter settings. Start floating left or right, exclude module\'s css and define selectors/rejectors.',
    'file' => 'autofloat.admin.inc',
  );
  return $items;
}

/**
 * Implements hook_filter_info().
 */
function autofloat_filter($op, $delta = 0, $format = -1, $text = '') {
  if ($op == 'list') {
    return array(
      0 => t('AutoFloat'),
    );
  }
  switch ($delta) {
    case 0:
      switch ($op) {
        case 'description':
          return t('Images will float left and right unless escaped with a class "nofloat".');
        case 'prepare':
          return $text;
        case 'process':
          return _autofloat($text, $format);
        case 'settings':
          $form['autofloat']['notice'] = array(
            '#value' => t('<p>These settings are shared by all the input formats where <em>Autofloat</em> is enabled:</p>'),
          );
          return $form;
      }
      break;
  }
}

/**
 * Returns the filter information for the filter help page.
 */
function autofloat_filter_tips($delta, $format, $long = FALSE) {
  $output = t('Images will float left and right unless escaped with <em>class="nofloat"</em>');
  return $output;
}

/**
 * Find a rejected 'div', a selected 'span', a link with image or an image.
 */
function _autofloat($text, $format) {
  $selector = variable_get('autofloat_span', 'flickr-wrap');

  // Divide the variable into two selectors if a comma is found.
  $selector = explode(',', $selector);

  // Make sure both array keys exist.
  if (isset($selector[0]) == FALSE) {
    $selector[0] = 'non-existing-class-value';
  }
  if (isset($selector[1]) == FALSE) {
    $selector[1] = 'non-existing-class-value';
  }
  $rejector = variable_get('autofloat_div', 'flickr-photoset');

  // Divide the variable into two rejectors if a comma is found.
  $rejector = explode(',', $rejector);

  // Make sure both array keys exist, if not the regex breaks.
  if (isset($rejector[0]) == FALSE) {
    $rejector[0] = 'non-existing-class-value';
  }
  if (isset($rejector[1]) == FALSE) {
    $rejector[1] = 'non-existing-class-value';
  }
  $count = 0;

  // Load string to DOMDocument.
  $doc = new DOMDocument();

  // Ignore warnings during HTML soup loading.
  @$doc
    ->loadHTML('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>' . $text . '</body></html>');
  $xpath = new DOMXPath($doc);

  // Iterate through the string neglecting elements nested inside those already
  // processed or those to reject.
  foreach ($xpath
    ->query('//span[contains(@class, "float") or contains(@class, "' . $selector[0] . '") or contains(@class, "' . $selector[1] . '")][not(ancestor::*[@class="nofloat"] or ancestor::*[@class="' . $rejector[0] . '"] or ancestor::*[@class="' . $rejector[1] . '"])] | //img[not(ancestor-or-self::*[contains(@class, "nofloat")] or ancestor-or-self::*[contains(@class, "' . $rejector[0] . '")] or ancestor-or-self::*[contains(@class, "' . $rejector[1] . '")] or ancestor::span[contains(@class, "float") or contains(@class, "' . $selector[0] . '") or contains(@class, "' . $selector[1] . '")])]') as $tag) {

    // Start on the left or right depending on the settings.
    if (variable_get('autofloat_start', 0) == 0) {
      $zebra = $count % 2 ? 'even' : 'odd';
    }
    else {
      $zebra = $count % 2 ? 'odd' : 'even';
    }
    $count++;

    // Add an alternating class value but maintain the existing ones.
    $tag
      ->setAttribute('class', 'autofloat-' . $zebra . ' ' . $tag
      ->getAttribute('class'));
  }

  // Convert a DOM object back to an HTML snippet.
  $body_node = $doc
    ->getElementsByTagName('body')
    ->item(0);
  $body_content = '';
  foreach ($body_node
    ->getElementsByTagName('script') as $node) {
    filter_dom_serialize_escape_cdata_element($doc, $node);
  }
  foreach ($body_node
    ->getElementsByTagName('style') as $node) {
    filter_dom_serialize_escape_cdata_element($doc, $node, '/*', '*/');
  }
  foreach ($body_node->childNodes as $child_node) {
    $body_content .= $doc
      ->saveXML($child_node);
  }
  return preg_replace('|<([^> ]*)/>|i', '<$1 />', $body_content);
}

Functions

Namesort descending Description
autofloat_filter Implements hook_filter_info().
autofloat_filter_tips Returns the filter information for the filter help page.
autofloat_help Implements hook_help().
autofloat_init Implements hook_init().
autofloat_menu Implements hook_menu().
_autofloat Find a rejected 'div', a selected 'span', a link with image or an image.