You are here

customfilter.module in Custom filter 5

File

customfilter.module
View source
<?php

define('CUSTOMFILTER_CODE_DECLARE', 'global $_customfilter_code_vars; $vars = & $_customfilter_code_vars;');
global $_customfilter_code_vars;
global $_customfilter_globals;

/**
 * Implements hook_filter().
 */
function customfilter_filter($op, $delta = 0, $format = -1, $text = '') {
  switch ($op) {
    case 'list':
      return _customfilter_filter_list();
    case 'no cache':
      return !_customfilter_filter_cache($delta);
    case 'description':
      return _customfilter_filter_desc($delta);
    case 'prepare':
      return $text;
    case 'process':
      return _customfilter_process($delta, $format, $text);
    default:
      return $text;
  }
}

/**
 * Implements hook_filter_tips().
 */
function customfilter_filter_tips($delta, $format, $long = FALSE) {
  $col = $long ? 'longtips' : 'shorttips';
  $tips = customfilter_get_set($delta, array(
    'sid',
    $col,
  ));
  return isset($tips[$col]) ? $tips[$col] : '';
}

/**
 * Implements hook_help().
 */
function customfilter_help($section) {
  $arg3 = arg(3);
  $arg4 = arg(4);
  $help = '';
  $sid = isset($arg3) && is_numeric($arg3) ? $arg3 : '';
  $fid = isset($arg4) && is_numeric($arg4) ? $arg4 : '';
  switch ($section) {
    case "admin/modules#description":
      $help = t('Custom Filter');
      break;
    case "admin/settings/customfilter":
      $help = '<p>' . t('Custom Filter provides an ability for creating user defined filters using regular expressions. Instead of creating filter modules, users can create their own filter for specific site purpose.') . '</p>';
      if (count(customfilter_get_sets()) > 0) {
        $help .= '<p>' . t('Below are the filter sets. ');
      }
      else {
        $help .= '<p>' . t('Before you can use custom filters, you must have at least one filter set. ');
      }
      $help .= t('Filter set is a container of filters. Each will appear in Input Format configuration. Click at their name to see what filter they have.') . '</p>';
      break;
    case "admin/settings/customfilter/export":
      $help = '<p>' . t('You can export your custom filters as XML document. Just check filters you want to export below, and click the button Export.') . '</p>';
      break;
    case "admin/settings/customfilter/import":
      $help = '<p>' . t('You can import custom filters from an XML file.') . '</p>';
      break;
    case "admin/settings/customfilter/{$sid}":
      $help = '<p>' . t('This filterset has filters listed below. Each filter can have subfilters.') . '</p>';
      break;
    case "admin/settings/customfilter/add":
    case "admin/settings/customfilter/{$sid}/edit":
      $help = '<p>' . t('Give this filter set some name and description.') . '</p>';
      break;
    case "admin/settings/customfilter/{$sid}/add":
    case "admin/settings/customfilter/{$sid}/{$fid}":
    case "admin/settings/customfilter/{$sid}/{$fid}/edit":
    case "admin/settings/customfilter/{$sid}/{$fid}/add":
      $help = '<p>' . t('Here you can define your own filters using regular expressions. For some information about regular expressions, please look at ') . l('http://www.regular-expressions.info', 'http://www.regular-expressions.info') . '</p>';
      break;
  }
  return $help;
}

/**
 * Implements hook_menu().
 */
function customfilter_menu($may_cache) {
  $access = user_access('administer customfilter');
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'admin/settings/customfilter',
      'title' => t('Custom Filter'),
      'description' => t('User defined filters.'),
      'callback' => 'customfilter_settings',
      'access' => $access,
      'type' => MENU_NORMAL_ITEM,
    );

    // Customfilter: List
    $items[] = array(
      'path' => 'admin/settings/customfilter/list',
      'title' => t('List'),
      'access' => $access,
      'type' => MENU_DEFAULT_LOCAL_TASK,
      'weight' => 1,
    );

    // Customfilter: Add filterset
    $items[] = array(
      'path' => 'admin/settings/customfilter/add',
      'title' => t('Add filter set'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'customfilter_set_edit',
        'add',
      ),
      'access' => $access,
      'type' => MENU_LOCAL_TASK,
      'weight' => 2,
    );

    // Customfilter: Export
    $items[] = array(
      'path' => 'admin/settings/customfilter/export',
      'title' => t('Export'),
      'callback' => 'drupal_get_form',
      'access' => $access,
      'callback arguments' => array(
        'customfilter_export_form',
      ),
      'type' => MENU_LOCAL_TASK,
      'weight' => 3,
    );

    // Customfilter: Import
    $items[] = array(
      'path' => 'admin/settings/customfilter/import',
      'title' => t('Import'),
      'callback' => 'drupal_get_form',
      'access' => $access,
      'callback arguments' => array(
        'customfilter_import_form',
      ),
      'type' => MENU_LOCAL_TASK,
      'weight' => 4,
    );

    // Customfilter: Get XML
    $items[] = array(
      'path' => 'admin/settings/customfilter/export/xml',
      'title' => t('XML'),
      'callback' => 'customfilter_xml_export',
      'access' => $access,
      'type' => MENU_CALLBACK,
    );
  }
  else {
    $arg0 = arg(0);
    $arg1 = arg(1);
    $arg2 = arg(2);
    $arg3 = arg(3);
    $arg4 = arg(4);
    $bool = isset($arg0) && $arg0 == 'admin' && isset($arg1) && $arg1 == 'settings' && isset($arg2) && $arg2 == 'customfilter' && isset($arg3) && is_numeric($arg3);
    if ($bool) {
      $sid = $arg3;
      $set = customfilter_get_set($sid, 'name');
      if ($set) {

        // Filterset: List filters
        $items[] = array(
          'path' => "admin/settings/customfilter/{$sid}",
          'title' => t("Custom filter: {$set['name']}"),
          'callback' => 'customfilter_filters',
          'callback arguments' => array(
            arg(3),
          ),
          'access' => $access,
          'type' => MENU_CALLBACK,
        );
        $items[] = array(
          'path' => "admin/settings/customfilter/{$sid}/list",
          'title' => t('List'),
          'access' => $access,
          'type' => MENU_DEFAULT_LOCAL_TASK,
          'weight' => 1,
        );

        // Filterset: Edit filterset
        $items[] = array(
          'path' => "admin/settings/customfilter/{$sid}/edit",
          'title' => t('Edit'),
          'callback' => 'drupal_get_form',
          'access' => $access,
          'callback arguments' => array(
            'customfilter_set_edit',
            'edit',
            $sid,
          ),
          'type' => MENU_LOCAL_TASK,
          'weight' => 2,
        );

        // Filterset: Delete filterset
        $items[] = array(
          'path' => "admin/settings/customfilter/{$sid}/delete",
          'title' => t('Delete'),
          'callback' => 'drupal_get_form',
          'access' => $access,
          'callback arguments' => array(
            'customfilter_set_delete',
            $sid,
          ),
          'type' => MENU_LOCAL_TASK,
          'weight' => 3,
        );

        // Filterset: Add filter
        $items[] = array(
          'path' => "admin/settings/customfilter/{$sid}/add",
          'title' => t('Add filter'),
          'callback' => 'drupal_get_form',
          'callback arguments' => array(
            'customfilter_filter_edit',
            'add',
            $sid,
          ),
          'access' => $access,
          'type' => MENU_LOCAL_TASK,
          'weight' => 4,
        );
        if (isset($arg4) && is_numeric($arg4)) {
          $fid = $arg4;

          // Select * if using static filters array as filter is cached for editing
          $filter = customfilter_get_filter($fid, '*');

          // Filter: List
          $items[] = array(
            'path' => "admin/settings/customfilter/{$sid}/{$fid}",
            'title' => t("Filter: {$filter['name']}"),
            'callback' => 'drupal_get_form',
            'callback arguments' => array(
              'customfilter_filter_edit',
              'edit',
              $sid,
              $fid,
            ),
            'access' => $access,
            'type' => MENU_CALLBACK,
          );

          // Filter: Edit filter
          $items[] = array(
            'path' => "admin/settings/customfilter/{$sid}/{$fid}/edit",
            'title' => t('Edit'),
            'access' => $access,
            'type' => MENU_DEFAULT_LOCAL_TASK,
            'weight' => 1,
          );

          // Filter: Delete filter
          $items[] = array(
            'path' => "admin/settings/customfilter/{$sid}/{$fid}/delete",
            'title' => t('Delete filter'),
            'callback' => 'drupal_get_form',
            'callback arguments' => array(
              'customfilter_filter_delete',
              $fid,
            ),
            'access' => $access,
            'type' => MENU_LOCAL_TASK,
            'weight' => 3,
          );

          // Filter: Add subfilter
          $items[] = array(
            'path' => "admin/settings/customfilter/{$sid}/{$fid}/add",
            'title' => t('Add subfilter'),
            'callback' => 'drupal_get_form',
            'callback arguments' => array(
              'customfilter_filter_edit',
              'add',
              $sid,
              $fid,
            ),
            'access' => $access,
            'type' => MENU_LOCAL_TASK,
            'weight' => 2,
          );
        }
      }
    }
  }
  return $items;
}

/**
 * Implements hook_perm().
 */
function customfilter_perm() {
  return array(
    'administer customfilter',
  );
}

/**
 * Export form.
 */
function customfilter_export_form() {
  $form = array();
  $sets = customfilter_get_sets();
  foreach ($sets as $set) {
    $opt[$set['sid']] = $set['name'];
  }
  $form['sets'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Filter sets'),
    '#options' => $opt,
    '#description' => 'Choose filter sets.',
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Export',
  );
  return $form;
}
function customfilter_export_form_submit($form_id, $form_values) {
  $sids = array();
  foreach ($form_values['sets'] as $sid) {
    if ($sid > 0) {
      $sids[] = $sid;
    }
  }
  $arg = join('.', $sids);
  return "admin/settings/customfilter/export/xml/{$arg}";
}

/**
 * List all the defined filters.
 */
function customfilter_filters($sid) {
  return customfilter_filter_render_table($sid, 0);
}

/**
 * Import form.
 */
function customfilter_import_form() {
  $form = array();
  $form['xml'] = array(
    '#type' => 'file',
    '#title' => t('Import from file'),
    '#description' => t('The XML file to be imported.'),
  );
  $form[] = array(
    '#type' => 'submit',
    '#value' => t('Import'),
  );
  $form['#attributes'] = array(
    'enctype' => 'multipart/form-data',
  );
  return $form;
}
function customfilter_import_form_submit($form_id, $form_values) {
  global $_customfilter_globals;
  if (!isset($_customfilter_globals)) {
    $_customfilter_globals = new stdClass();
  }
  $cg =& $_customfilter_globals;
  if ($file = file_check_upload('xml')) {
    if ($thefile = fopen($file->filepath, "rb")) {
      $fstat = fstat($thefile);
      $xml = fread($thefile, $fstat['size']);
      fclose($thefile);
      drupal_set_message(t('XML file %f imported.', array(
        '%f' => $file->filename,
      )));
      customfilter_xml_read($xml);
      _customfilter_xml_sql($cg->sets, $cg->filters);
    }
  }
}

/**
 * Delete a filter set.
 */
function customfilter_set_delete($sid) {
  $filters = customfilter_get_filters($sid);
  $set = customfilter_get_set($sid, '*');
  $form['sid'] = array(
    '#type' => 'value',
    '#value' => $sid,
  );
  $message = t('Are you sure you want to delete this filter set?');
  $msg_text = "<h3>" . $set['name'] . "</h3>" . "<p>" . $set->description . "</p>";
  if (count($filters) > 0) {
    $msg_text .= "<p>" . t('This set has filters. If you delete this, they will be deleted too.') . "</p>" . customfilter_filter_render_table($sid, $fid, FALSE);
  }
  $msg_text .= "<p>" . t('This action cannot be undone.') . "</p>";
  return confirm_form($form, $message, 'admin/settings/customfilter', $msg_text, t('Delete'));
}

/**
 * Delete the filter set.
 */
function customfilter_set_delete_submit($form_id, $form_values) {
  customfilter_delete_set($form_values['sid']);
  return 'admin/settings/customfilter';
}

/**
 * Edit a filter set.
 */
function customfilter_set_edit($op, $sid = 0) {
  switch ($op) {
    case 'edit':
      $item = customfilter_get_set($sid, '*');
      break;
    case 'add':
      $item = array(
        'sid' => 0,
        'name' => 'Filter set #',
        'cache' => 1,
        'description' => '',
        'shorttips' => '',
        'longtips' => '',
      );
      break;
  }
  $form['sid'] = array(
    '#type' => 'value',
    '#value' => $item['sid'],
  );
  $form['operation'] = array(
    '#type' => 'value',
    '#value' => $op,
  );
  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
    '#default_value' => $item['name'],
    '#description' => t('The name of the filter set.'),
    '#required' => TRUE,
  );
  $form['cache'] = array(
    '#type' => 'checkbox',
    '#title' => t('Cache'),
    '#default_value' => $item['cache'],
    '#description' => t('If checked, the content will be cached (i.e. this filter will be executed once per content edit).'),
  );
  $form['description'] = array(
    '#type' => 'textarea',
    '#title' => t('Description'),
    '#default_value' => $item['description'],
    '#description' => t('Some text to describe this filter set.'),
  );
  $form['shorttips'] = array(
    '#type' => 'textarea',
    '#title' => t('Tips (short)'),
    '#default_value' => $item['shorttips'],
    '#description' => '',
  );
  $form['longtips'] = array(
    '#type' => 'textarea',
    '#title' => t('Tips (full)'),
    '#default_value' => $item['longtips'],
    '#description' => '',
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
  );
  return $form;
}

/**
 * Submit the modified filter set.
 */
function customfilter_set_edit_submit($form_id, $form_values) {
  switch ($form_values['operation']) {
    case 'edit':
      db_query("UPDATE {customfilter_set}\n        SET name = '%s', cache = %d, description = '%s', shorttips = '%s', longtips = '%s'\n        WHERE sid = %d", $form_values['name'], $form_values['cache'], $form_values['description'], $form_values['shorttips'], $form_values['longtips'], $form_values['sid']);
      break;
    case 'add':
      $nextid = db_next_id('{customfilter_set}_sid');
      db_query("INSERT INTO {customfilter_set} (sid, name, cache, description, shorttips, longtips) VALUES (%d, '%s', %d, '%s', '%s', '%s');", $nextid, $form_values['name'], $form_values['cache'], $form_values['description'], $form_values['shorttips'], $form_values['longtips']);
      break;
  }
  return 'admin/settings/customfilter';
}

/**
 * Administration page.
 */
function customfilter_settings() {
  $header = array(
    t('Name'),
    t('Description'),
    array(
      'data' => t('Operations'),
      'colspan' => '2',
    ),
  );
  $rows = customfilter_set_get_rows();
  $table = theme('table', $header, $rows ? $rows : array(
    array(
      array(
        'data' => t('No custom filter defined.'),
        'colspan' => 5,
      ),
    ),
  ));
  return $table;
}

/**
 * Delete a filter.
 */
function customfilter_filter_delete($fid) {
  $filter = db_fetch_object(db_query("SELECT * FROM {customfilter_filter} WHERE fid = %d", $fid));
  $subfilter = db_fetch_object(db_query("SELECT * FROM {customfilter_filter} WHERE parentid = %d", $fid));
  $form['fid'] = array(
    '#type' => 'value',
    '#value' => $fid,
  );
  $form['sid'] = array(
    '#type' => 'value',
    '#value' => $filter->sid,
  );
  $message = t('Are you sure you want to delete this custom filter?');
  $msg_text = ($filter->parentid == 0 ? "<h3>{$filter->name}</h3>" : "") . "<p>{$filter->description}</p>" . "<h3>Pattern</h3>" . "<pre>{$filter->pattern}</pre>" . "<h3>Replacer</h3>" . "<pre>{$filter->replacer}</pre>";
  if ($subfilter) {
    $msg_text .= "<p>" . t('This filter has subfilters. If you delete this, they will be deleted too.') . "</p>" . customfilter_filter_render_table($filter->sid, $fid, FALSE);
  }
  $msg_text .= "<p>" . t('This action cannot be undone.') . "</p>";
  return confirm_form($form, $message, "admin/settings/customfilter/{$filter->sid}", $msg_text, t('Delete'));
}

/**
 * Delete the selected filter.
 */
function customfilter_filter_delete_submit($form_id, $form_values) {
  customfilter_delete_filter($form_values['fid']);
  return "admin/settings/customfilter/{$form_values['sid']}";
}

/**
 * Edit a filter.
 */
function customfilter_filter_edit($op, $sid, $fid = 0) {
  if ($op == 'edit') {
    $item = customfilter_get_filter($fid, '*');
  }
  elseif ($op == 'add') {
    $item = array(
      'fid' => 0,
      'parentid' => $fid,
      'sid' => $sid,
      'name' => '$1',
      'description' => '',
      'matches' => 1,
      'pattern' => '/regex/i',
      'replacement' => 'Regular Expressions',
      'func' => 0,
      'weight' => 0,
    );
  }
  $matchopt = array();
  for ($i = 0; $i <= 99; $i++) {
    $matchopt[$i] = $i;
  }
  $form['fid'] = array(
    '#type' => 'value',
    '#value' => $item['fid'],
  );
  $form['sid'] = array(
    '#type' => 'value',
    '#value' => $sid,
  );
  $form['parentid'] = array(
    '#type' => 'value',
    '#value' => $item['parentid'],
  );
  $form['operation'] = array(
    '#type' => 'value',
    '#value' => $op,
  );
  if ($item['parentid'] != 0) {
    $form['matches'] = array(
      '#type' => 'select',
      '#title' => t('# Match'),
      '#options' => $matchopt,
      '#default_value' => $item['matches'],
      '#description' => t('Matches.'),
    );
  }
  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
    '#default_value' => $item['name'],
    '#description' => t('The name of the filter.'),
    '#required' => TRUE,
  );
  $form['pattern'] = array(
    '#type' => 'textarea',
    '#title' => t('Pattern'),
    '#default_value' => $item['pattern'],
    '#description' => t('Regular expression. Look at <a href="http://www.regular-expressions.info">http://www.regular-expressions.info</a> for more help.'),
  );
  $form['replacement'] = array(
    '#type' => 'textarea',
    '#title' => t('Replacement text'),
    '#default_value' => $item['replacement'],
    '#description' => t('Replacement Text. Matched string will be replaced with text supplied here. Use $n (e.g. $1, $25) or ${n} (e.g. ${1}, ${25}), with n range from 0 to 99, to get the n-th original strings matched ($0 represents the entire matched string). If you set the <strong>PHP Code</strong> below, you can enter replaced text with some PHP Code. n-th matched string will be provided in $matches[n], and there will be a global variable named $vars you can use it for your own purpose. Don\'t forget to write the return statement.'),
  );
  $form['func'] = array(
    '#type' => 'checkbox',
    '#title' => t('PHP Code'),
    '#default_value' => $item['func'],
    '#description' => t('Check to allow using PHP code to replace the text.'),
  );
  $form['weight'] = array(
    '#type' => 'weight',
    '#title' => t('Weight'),
    '#default_value' => $item['weight'],
    '#description' => t('Filter weight.'),
  );
  $form['description'] = array(
    '#type' => 'textarea',
    '#title' => t('Description'),
    '#default_value' => $item['description'],
    '#description' => t('Some text to describe this filter.'),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save Configuration'),
  );
  return $form;
}

/**
 * Save the modified filter.
 */
function customfilter_filter_edit_submit($form_id, $form_values) {
  switch ($form_values['operation']) {
    case 'edit':
      db_query("UPDATE {customfilter_filter} SET sid = %d, parentid = %d, name = '%s', description = '%s', matches = %d, pattern = '%s', replacement = '%s', func = %d, weight = %d\n        WHERE fid = %d", $form_values['sid'], $form_values['parentid'], $form_values['name'], $form_values['description'], $form_values['matches'], $form_values['pattern'], $form_values['replacement'], $form_values['func'], $form_values['weight'], $form_values['fid']);
      break;
    case 'add':
      $nextid = db_next_id('{customfilter_filter}_fid');
      db_query("INSERT INTO {customfilter_filter} (fid, sid, parentid, name, description, matches, pattern, replacement, func, weight) VALUES (%d, %d, %d, '%s', '%s', %d, '%s', '%s', %d, %d);", $nextid, $form_values['sid'], $form_values['parentid'], $form_values['name'], $form_values['description'], $form_values['matches'], $form_values['pattern'], $form_values['replacement'], $form_values['func'], $form_values['weight']);
      break;
  }
  return "admin/settings/customfilter/{$form_values['sid']}";
}
function customfilter_delete_filter($fid) {
  $result = db_query("SELECT * FROM {customfilter_filter} where parentid = %d", $fid);
  while ($filter = db_fetch_object($result)) {
    customfilter_delete_filter($filter->fid);
  }
  db_query("DELETE FROM {customfilter_filter} WHERE fid = %d", $fid);
}
function customfilter_delete_set($sid) {
  $filters = customfilter_get_filters($sid);
  foreach ($filters as $filter) {
    customfilter_delete_filter($filter['fid']);
  }
  db_query('DELETE FROM {customfilter_set} WHERE sid = %d', $sid);
}

/**
 * Render the table rows of filter table.
 *
 * @param $filters
 *   Array of fetched filters from database (returned by customfilter_get_filters()).
 * @param $depth
 *   The level of subfilters that should be rendered.
 * @param $rows
 *   The generated rows.
 * @param $op
 *   If TRUE, it will render the column 'operations'.
 */
function customfilter_filter_get_rows($filters, $depth, &$rows, $op = TRUE) {
  $rows = array();
  foreach ($filters as $filter) {
    $format = $depth == 0 ? "strong" : "em";
    $row = array(
      str_repeat('&raquo;&nbsp;', $depth) . '<' . $format . '>' . $filter['name'] . '</' . $format . '>',
      '<em>' . $filter['description'] . '</em>',
      htmlspecialchars($filter['pattern']),
      $filter['parentid'] == 0 ? "" : $filter['matches'],
      $filter['weight'],
    );
    if ($op) {
      $row[] = l(t('add'), "admin/settings/customfilter/{$filter['sid']}/{$filter['fid']}/add");
      $row[] = l(t('edit'), "admin/settings/customfilter/{$filter['sid']}/{$filter['fid']}/edit");
      $row[] = l(t('delete'), "admin/settings/customfilter/{$filter['sid']}/{$filter['fid']}/delete");
    }
    $rows[] = $row;
    if (!empty($filter['sub']) && is_array($filter['sub'])) {
      customfilter_filter_get_rows($filter['sub'], $depth + 1, $rows, $op);
    }
  }
}

/**
 * Render the table of filters.
 *
 * @param $sid
 *   ID of the filter set.
 * @param $fid
 *   ID of the root filter.
 * @param $op
 *   If TRUE, will render the 'operations' column.
 *
 * @return
 *   Themed table of filters.
 */
function customfilter_filter_render_table($sid = 0, $fid = 0, $op = TRUE) {
  $filters = customfilter_get_filters($sid, $fid);
  $header = array(
    t('Name'),
    t('Description'),
    t('Pattern'),
    t('Match'),
    t('Weight'),
  );
  $rows = array();
  if ($op) {
    $header[] = array(
      'data' => t('Operations'),
      'colspan' => '3',
    );
  }
  if (count($filters) > 0) {
    customfilter_filter_get_rows($filters, 0, $rows, $op);
  }
  else {
    $rows[] = array(
      0 => array(
        'data' => t('No custom filter defined.'),
        'colspan' => 5,
      ),
    );
  }
  $table = theme('table', $header, $rows);
  return $table;
}

/**
 * Get complete description of a filter, including its subfilters.
 */
function customfilter_get_descriptions($filter) {
  $desc = "<em>" . $filter['description'] . "</em>";
  if (is_array($filter['sub']) && count($filter['sub']) > 0) {
    $desc .= "<ul>";
    foreach ($filter['sub'] as $subfilter) {
      $desc .= "<li>";
      $desc .= customfilter_get_descriptions($subfilter);
      $desc .= "</li>";
    }
    $desc .= "</ul>";
  }
  return $desc;
}

/**
 * Get a filter from the database.
 *
 * @param $fid
 *   ID of the filter.
 * @param $cols
 *   The columns to retrive.
 *
 * @return
 *   The filter.
 */
function customfilter_get_filter($fid, $cols = '*') {
  static $filters;
  if (!is_array($filters)) {
    $filters = array();
  }
  if (!isset($filters[$fid])) {

    // Prepare columns to select
    if (!is_array($cols)) {
      $cols = array(
        $cols,
      );
    }
    $columns = join(', ', $cols);
    $filter = db_fetch_array(db_query("SELECT {$columns} FROM {customfilter_filter} WHERE fid = %d", $fid));
    $filters[$fid] = $filter;
  }
  return $filters[$fid];
}

/**
 * Get filters from database
 *
 * @param $sid
 *   ID of the filter set.
 * @param $root
 *   The root filter. Return the tree of filters with this filter as the root.
 * @param $sortby
 *   Sort the result (and subfilters) by this field (default: sort by weight).
 *
 * @return
 *   Array of filters (each have ['sub'], contains subfilters if any).
 */
function customfilter_get_filters($sid, $root = 0, $sortby = 'weight', $cols = '*') {
  static $filters;
  if (!is_array($filters)) {
    $filters = array();
  }
  if (!isset($filters[$sid]) || $root > 0) {

    // Prepare columns to select
    if (!is_array($cols)) {
      $cols = array(
        $cols,
      );
    }
    $columns = join(', ', $cols);

    // Prepare nodes
    $nodes = array();
    if (is_array($root)) {
      $nodes = $root;
    }
    else {
      $nodes = array(
        $root,
      );
    }
    foreach ($nodes as $node) {
      $result = db_query("SELECT {$columns} FROM {customfilter_filter} WHERE sid = %d and parentid = %d ORDER BY {$sortby}", $sid, $node);
      while ($filter = db_fetch_array($result)) {
        $filter['sub'] = customfilter_get_filters($sid, $filter['fid'], $sortby, $cols);
        $filters[$sid][$filter['fid']] = $filter;
      }
    }
  }
  return $filters[$sid];
}

/**
 * Get a filter set from the database.
 *
 * @param $sid
 *   ID of the filterset.
 * @param $cols
 *   The columns to retrieve.
 *
 * @return
 *   The filter set.
 */
function customfilter_get_set($sid, $cols = array(
  'sid',
  'name',
  'description',
)) {
  static $sets;
  if (!is_array($sets)) {
    $sets = array();
  }
  if (!$sets[$sid]) {

    // Prepare columns to select
    if (!is_array($cols)) {
      $cols = array(
        $cols,
      );
    }
    $columns = join(', ', $cols);

    // Query & Fetch
    $set = db_fetch_array(db_query("SELECT {$columns} FROM {customfilter_set} WHERE sid = %d", $sid));
    $sets[$sid] = $set;
  }
  return $sets[$sid];
}

/**
 * Get filter sets from database.
 *
 * @param $cols
 *   Columns to be retrieved.
 * @param $cond
 *   Condition, return all results by default.
 *
 * @return
 *   Array of filter sets.
 */
function customfilter_get_sets($cols = array(
  'sid',
  'name',
  'description',
), $cond = '1=1') {
  static $sets;
  if (!isset($sets)) {
    $sets = array();

    // Prepare columns to select
    if (!is_array($cols)) {
      $cols = array(
        $cols,
      );
    }
    $columns = join(', ', $cols);

    // Query & fetch
    $result = db_query("SELECT {$columns} FROM {customfilter_set} WHERE {$cond} ORDER BY name");
    while ($set = db_fetch_array($result)) {
      $sets[] = $set;
    }
  }
  return $sets;
}
function customfilter_set_get_rows() {
  $sets = customfilter_get_sets();
  foreach ($sets as $set) {
    $rows[] = array(
      l($set['name'], "admin/settings/customfilter/{$set['sid']}"),
      '<em>' . $set['description'] . '</em>',
      l(t('edit'), "admin/settings/customfilter/{$set['sid']}/edit"),
      l(t('delete'), "admin/settings/customfilter/{$set['sid']}/delete"),
    );
  }
  return $rows;
}
function customfilter_xml_create($sids) {
  $xml = "<?xml version=\"1.0\" standalone=\"yes\"?>\n";
  $xml .= "<customfilter>\n";
  foreach ($sids as $sid) {
    $xml .= customfilter_xml_filterset($sid);
  }
  $xml .= "</customfilter>";
  return $xml;
}
function customfilter_xml_export($sets) {
  $sids = explode('.', $sets);
  $xml = customfilter_xml_create($sids);
  header('Content-Type: application/octet-stream');
  header('Content-Length: ' . strlen($xml));
  header("Content-Disposition: attachment; filename=customfilter.xml");
  echo $xml;
}
function customfilter_xml_filter($filter, $level = 0) {
  $indent = str_repeat('  ', $level + 3);
  $xml = $indent . "<filter name=\"{$filter['name']}\" matches=\"{$filter['matches']}\" func=\"{$filter['func']}\" weight=\"{$filter['weight']}\">\n";
  $xml .= $indent . "  <description><![CDATA[{$filter['description']}]]></description>\n";
  $xml .= $indent . "  <pattern><![CDATA[{$filter['pattern']}]]></pattern>\n";
  $xml .= $indent . "  <replacement><![CDATA[{$filter['replacement']}]]></replacement>\n";
  $subfilters = $filter['sub'];
  if (is_array($subfilters) && count($subfilters) > 0) {
    $xml .= $indent . "  <subfilters>\n";
    foreach ($subfilters as $subfilter) {
      $xml .= customfilter_xml_filter($subfilter, $level + 2);
    }
    $xml .= $indent . "  </subfilters>\n";
  }
  $xml .= $indent . "</filter>\n";
  return $xml;
}
function customfilter_xml_filterset($sid) {
  $filters = customfilter_get_filters($sid, 0);
  $set = customfilter_get_set($sid, '*');
  $xml = "  <filterset name=\"{$set['name']}\" cache=\"{$set['cache']}\">\n";
  $xml .= "    <description>{$set['description']}</description>\n";
  $xml .= "    <tips>\n";
  $xml .= "      <short><![CDATA[{$set['shorttips']}]]></short>\n";
  $xml .= "      <long><![CDATA[{$set['longtips']}]]></long>\n";
  $xml .= "    </tips>\n";
  $xml .= "    <filters>\n";
  foreach ($filters as $filter) {
    $xml .= customfilter_xml_filter($filter);
  }
  $xml .= "    </filters>\n";
  $xml .= "  </filterset>\n";
  return $xml;
}
function customfilter_xml_read(&$xml) {
  global $_customfilter_globals;
  $cg =& $_customfilter_globals;
  $cg->elements = array();
  $cg->sets = array();
  $cg->filters = array();
  $cg->set = array();
  $cg->filter = array();
  $cg->parents = array();
  $parser = drupal_xml_parser_create($xml);
  xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
  xml_set_element_handler($parser, '_customfilter_xml_element_start', '_customfilter_xml_element_end');
  xml_set_character_data_handler($parser, '_customfilter_xml_element_cdata');
  xml_parse($parser, $xml, TRUE);
  xml_parser_free($parser);
}
function _customfilter_filter_cache($delta) {
  $set = customfilter_get_set($delta, array(
    'sid',
    'cache',
  ));
  return $set['cache'];
}
function _customfilter_filter_desc($delta) {
  $set = customfilter_get_set($delta, array(
    'sid',
    'description',
  ));
  return $set['description'];
}
function _customfilter_filter_list() {
  $s = array();
  $sets = customfilter_get_sets('sid, name');
  foreach ($sets as $set) {
    $s[$set['sid']] = $set['name'];
  }
  return $s;
}

/**
 * Filter process function.
 */
function _customfilter_process($delta, $format, $text) {
  global $_customfilter_globals;
  if (!isset($_customfilter_globals)) {
    $_customfilter_globals = new stdClass();
  }
  $_customfilter_globals->text = $text;

  // Get the filter set, according to $delta
  if ($set = customfilter_get_set($delta, 'sid')) {
    $filters = customfilter_get_filters($delta);
    if (count($filters) > 0) {

      // Preparation
      // The stack is used to save the parent filter when traversing
      $_customfilter_globals->stack = array();
      foreach ($filters as $filter) {
        $_customfilter_globals->stack[] = $filter;
        $_customfilter_globals->text = preg_replace_callback($filter['pattern'], '_customfilter_process_filter', $_customfilter_globals->text);
        array_pop($_customfilter_globals->stack);
      }
    }
  }
  return $_customfilter_globals->text;
}
function _customfilter_process_extract_rep($replacement) {
  $arr = array();
  $reps = array();
  preg_match_all('/([^\\\\]|^)(\\$([0-9]{1,2}|\\{([0-9]{1,2})\\}))/', $replacement, $reps, PREG_OFFSET_CAPTURE);
  foreach ($reps[4] as $key => $val) {
    if ($val == '') {
      $str = $reps[3][$key][0];
    }
    else {
      $str = $reps[4][$key][0];
    }
    $offset = $reps[2][$key][1];
    $length = strlen($reps[2][$key][0]);
    $arr[] = array(
      'index' => $str,
      'offset' => $offset,
      'length' => $length,
    );
  }
  return $arr;
}
function _customfilter_process_filter($matches) {
  global $_customfilter_globals;
  $result = $matches[0];
  $filter = end($_customfilter_globals->stack);

  // if there is subfilter
  if (is_array($filter['sub']) && count($filter['sub']) > 0) {

    // do the same thing to each of them
    foreach ($filter['sub'] as $subfilter) {
      $_customfilter_globals->stack[] = $subfilter;
      $substr =& $matches[$subfilter['matches']];
      $substr = preg_replace_callback($subfilter['pattern'], '_customfilter_process_filter', $substr);
      array_pop($_customfilter_globals->stack);
    }
    $result = _customfilter_process_replace_sub($filter['replacement'], $matches, $filter['func']);
  }
  elseif ($filter['func'] == 1) {
    $result = preg_replace_callback($filter['pattern'], create_function('$matches', CUSTOMFILTER_CODE_DECLARE . $filter['replacement']), $result);
  }
  else {
    $result = preg_replace($filter['pattern'], $filter['replacement'], $result);
  }
  return $result;
}
function _customfilter_process_replace_sub($replacement, $sub, $func = 0) {
  if ($func == 1) {
    $code = create_function('$matches', CUSTOMFILTER_CODE_DECLARE . $replacement);
    $text = $code($sub);
  }
  else {
    $text = $replacement;
    $reps = _customfilter_process_extract_rep($replacement);
    krsort($reps);
    foreach ($reps as $rep) {
      $text = substr_replace($text, $sub[$rep['index']], $rep['offset'], $rep['length']);
    }
  }
  return $text;
}
function _customfilter_xml_element_cdata($parser, $data) {
  global $_customfilter_globals;
  $cg =& $_customfilter_globals;
  $element = end($cg->elements);
  $context = prev($cg->elements);
  switch ($element) {
    case 'DESCRIPTION':
      if ($context == 'FILTERSET') {
        $cg->set['description'] = $data;
      }
      elseif ($context == 'FILTER') {
        $cg->filter['description'] = $data;
      }
      break;
    case 'SHORT':
    case 'LONG':
      $cg->set[strtolower($element) . 'tips'] = $data;
      break;
    case 'PATTERN':
    case 'REPLACEMENT':
      $cg->filter[strtolower($element)] = $data;
      break;
  }
}
function _customfilter_xml_element_end($parser, $name) {
  global $_customfilter_globals;
  $cg =& $_customfilter_globals;
  switch ($name) {
    case 'FILTERSET':
      $cg->sets[$cg->set['sid']] = $cg->set;
      $cg->set = array();
      break;
    case 'FILTER':
      $cg->filters[$cg->filter['fid']] = $cg->filter;
      $cg->filter = array();
      break;
    case 'SUBFILTERS':
      $cg->filter = array_pop($cg->parents);
      break;
  }
  array_pop($cg->elements);
}
function _customfilter_xml_element_start($parser, $name, $attr) {
  global $_customfilter_globals;
  $cg =& $_customfilter_globals;
  $cg->elements[] = $name;
  switch ($name) {
    case 'FILTERSET':
      $cg->set['sid'] = db_next_id('{customfilter_set}_sid');
      $cg->set['name'] = $attr['NAME'];
      $cg->set['cache'] = $attr['CACHE'];
      $cg->set['description'] = '';
      $cg->set['shorttips'] = '';
      $cg->set['longtips'] = '';
      break;
    case 'FILTER':
      $cg->filter['fid'] = db_next_id('{customfilter_filter}_fid');
      $cg->filter['sid'] = $cg->set['sid'];
      $cg->filter['name'] = $attr['NAME'];
      $cg->filter['matches'] = $attr['MATCHES'];
      $cg->filter['func'] = $attr['FUNC'];
      $cg->filter['weight'] = $attr['WEIGHT'];
      $cg->filter['description'] = '';
      $cg->filter['pattern'] = '';
      $cg->filter['replacement'] = '';
      if (count($cg->parents) > 0) {
        $parent = end($cg->parents);
        $cg->filter['parentid'] = $parent['fid'];
      }
      else {
        $cg->filter['parentid'] = 0;
      }
      break;
    case 'SUBFILTERS':
      $cg->parents[] = $cg->filter;
      $cg->filter = array();
      break;
    case 'FILTERS':
      $cg->parents = array();
      $cg->filter = array();
      break;
  }
}
function _customfilter_xml_sql($sets, $filters) {
  foreach ($sets as $set) {
    db_query("INSERT INTO {customfilter_set} (sid, name, cache, description, shorttips, longtips) VALUES (%d, '%s', %d, '%s', '%s', '%s');", $set['sid'], $set['name'], $set['cache'], $set['description'], $set['shorttips'], $set['longtips']);
  }
  foreach ($filters as $filter) {
    db_query("INSERT INTO {customfilter_filter} (fid, sid, parentid, name, description, matches, pattern, replacement, func, weight) VALUES (%d, %d, %d, '%s', '%s', %d, '%s', '%s', %d, %d);", $filter['fid'], $filter['sid'], $filter['parentid'], $filter['name'], $filter['description'], $filter['matches'], $filter['pattern'], $filter['replacement'], $filter['func'], $filter['weight']);
  }
}

Functions

Namesort descending Description
customfilter_delete_filter
customfilter_delete_set
customfilter_export_form Export form.
customfilter_export_form_submit
customfilter_filter Implements hook_filter().
customfilter_filters List all the defined filters.
customfilter_filter_delete Delete a filter.
customfilter_filter_delete_submit Delete the selected filter.
customfilter_filter_edit Edit a filter.
customfilter_filter_edit_submit Save the modified filter.
customfilter_filter_get_rows Render the table rows of filter table.
customfilter_filter_render_table Render the table of filters.
customfilter_filter_tips Implements hook_filter_tips().
customfilter_get_descriptions Get complete description of a filter, including its subfilters.
customfilter_get_filter Get a filter from the database.
customfilter_get_filters Get filters from database
customfilter_get_set Get a filter set from the database.
customfilter_get_sets Get filter sets from database.
customfilter_help Implements hook_help().
customfilter_import_form Import form.
customfilter_import_form_submit
customfilter_menu Implements hook_menu().
customfilter_perm Implements hook_perm().
customfilter_settings Administration page.
customfilter_set_delete Delete a filter set.
customfilter_set_delete_submit Delete the filter set.
customfilter_set_edit Edit a filter set.
customfilter_set_edit_submit Submit the modified filter set.
customfilter_set_get_rows
customfilter_xml_create
customfilter_xml_export
customfilter_xml_filter
customfilter_xml_filterset
customfilter_xml_read
_customfilter_filter_cache
_customfilter_filter_desc
_customfilter_filter_list
_customfilter_process Filter process function.
_customfilter_process_extract_rep
_customfilter_process_filter
_customfilter_process_replace_sub
_customfilter_xml_element_cdata
_customfilter_xml_element_end
_customfilter_xml_element_start
_customfilter_xml_sql

Constants

Globals