You are here

xbbcode_list.module in Extensible BBCode 5

File

xbbcode_list/xbbcode_list.module
View source
<?php

function xbbcode_list_xbbcode($op = 'list', $delta = '', $tag = NULL) {
  $tags['list'] = array(
    'dynamic' => true,
    'description' => t("Formats a list of items in the default style."),
  );
  $tags['ol'] = array(
    'dynamic' => true,
    'description' => t("Formats a numbered list of items."),
  );
  $tags['ul'] = array(
    'dynamic' => true,
    'description' => t("Formats a non-numbered list of items."),
  );
  switch ($op) {
    case 'list':
      return array_keys($tags);
    case 'info':
      return $tags[$delta];
    case 'render':
      return xbbcode_list_render($delta, $tag->option, $tag->content);
  }
}
function xbbcode_list_render($type, $style, $content) {
  drupal_add_css(drupal_get_path('module', 'xbbcode_list') . "/xbbcode_list.css");
  if ($type == 'list') {
    $type = variable_get('xbbcode_list_default', 'ul');
  }
  if (!$style) {
    $style = 'default';
  }
  global $xbbcode_list_styles;
  $content = xbbcode_list_armor_nested($content);
  $items = xbbcode_list_split_items($content);
  $class = $xbbcode_list_styles[$type][$style];
  $out = xbbcode_list_render_recursive($type, $class, $items);
  $out = preg_replace('/\\[(\\*+)--\\]/', '[$1]', $out);
  return $out;
}
function xbbcode_list_armor_nested($text) {
  $text = preg_replace('/(\\[list\\])(.*?)(\\[\\/list\\])(.*?)*/ie', 'xbbcode_list_armor_nested_("$1","$2","$3",$4")', $text);
  $text = preg_replace('/(\\[ol\\])(.*?)(\\[\\/ol\\])(.*?)*/ie', 'xbbcode_list_armor_nested_("$1","$2","$3","$4")', $text);
  $text = preg_replace('/(\\[ul\\])(.*?)(\\[\\/ul\\])(.*?)*/ie', 'xbbcode_list_armor_nested_("$1","$2","$3","$4")', $text);
  return $text;
}
function xbbcode_list_armor_nested_($open, $items, $close, $rest) {
  return $open . preg_replace('/\\[(\\*+)\\]/', '[$1--]', $items) . $close . $rest;
}
function xbbcode_list_split_items($text, $level = 1) {
  $items = preg_split('/\\[\\*{' . $level . ',' . $level . '}\\]/', $text);
  foreach ($items as $i => $item) {
    $items[$i] = trim($item);
  }
  if (count($items) > 1) {
    $parent = array_shift($items);
  }
  foreach ($items as $i => $item) {
    if (preg_match('/\\[\\*{' . ($level + 1) . ',' . ($level + 1) . '}\\]/', $item)) {
      $items[$i] = xbbcode_list_split_items($item, $level + 1);
    }
  }
  $items['#parent'] = $parent;
  return $items;
}
function xbbcode_list_render_recursive($tag, $classes, $items) {
  $class = is_array($classes) ? array_shift($classes) : $classes;
  if (!$classes) {
    $classes = $class;
  }
  $out = "<{$tag} class='{$class}'>";
  unset($items['#parent']);
  foreach ($items as $item) {
    if (is_array($item)) {
      $item = $item['#parent'] . xbbcode_list_render_recursive($tag, $classes, $item);
    }
    $out .= "<li>{$item}</li>";
  }
  $out .= "</{$tag}>";
  return $out;
}
function xbbcode_list_init() {
  global $xbbcode_list_styles;
  $xbbcode_list_styles['ol']['hierarchy'] = preg_split('/ *, */', variable_get('xbbcode_list_ol_hierarchy', 'numeric, lower-alpha, lower-roman'));
  $xbbcode_list_styles['ol']['sectioned'] = 'sectioned';
  $xbbcode_list_styles['ol']['default'] = $xbbcode_list_styles['ol'][variable_get('xbbcode_list_ol_default', 'hierarchy')];
}
function xbbcode_list_menu($maycache) {
  if ($maycache) {
    return;
  }
  $menu[] = array(
    'path' => 'admin/settings/xbbcode/lists/autocomplete',
    'title' => t("list-style-type autocomplete"),
    'callback' => 'xbbcode_list_autocomplete',
    'access' => user_access('administer site settings'),
    'type' => MENU_CALLBACK,
  );
  $menu[] = array(
    'path' => 'admin/settings/xbbcode/lists',
    'title' => t("List styles"),
    'callback' => 'drupal_get_form',
    'callback arguments' => 'xbbcode_list_admin_settings',
    'access' => user_access('administer site settings'),
    'type' => MENU_NORMAL_ITEM,
  );
  return $menu;
}
function xbbcode_list_admin_settings() {
  $form = array();
  $form['xbbcode_list_default'] = array(
    '#type' => 'radios',
    '#title' => t("Default list type"),
    '#description' => t("Choose whether [list] is numbered or non-numbered by default. Users can override the default by using [ul] or [ol]."),
    '#options' => array(
      'ol' => t("Numbered"),
      'ul' => t("Non-numbered"),
    ),
    '#default_value' => variable_get('xbbcode_list_default', 'ul'),
  );
  $form['ol'] = array(
    '#type' => 'fieldset',
    '#title' => t("Ordered list settings"),
    '#collapsible' => true,
    '#collapsed' => true,
    '#description' => t("Configure how to display lists with numbered items."),
  );
  $form['ul'] = array(
    '#type' => 'fieldset',
    '#title' => t("Unordered list settings"),
    '#collapsible' => true,
    '#collapsed' => true,
    '#description' => t("Configure how to display lists with numbered items."),
  );
  $form['ol']['xbbcode_list_ol_default'] = array(
    '#type' => 'radios',
    '#title' => t("Ordered list default"),
    '#description' => t("Ordered lists will look like this by default. The style can be overridden with [ol=dotted] and [ol=levels]"),
    '#options' => array(
      'sectioned' => t("Sectioned: <br />" . "<ol class='sectioned'>" . "  <li>Level 1" . "    <ol class='sectioned'>" . "      <li>Level 2" . "        <ol class='sectioned'>" . "          <li>Level 3</li>" . "          <li>Level 3, 2</li>" . "        </ol>" . "      </li>" . "    </ol>" . "  </li>" . "</ol>" . "<strong>Sectioned lists require a browser with CSS 2.0 support.</strong>"),
      'hierarchy' => t("Levels: <br />" . "<ol class='numeric'>" . "  <li>Level 1" . "    <ol class='lower-alpha'>" . "      <li>Level 2" . "        <ol class='lower-roman'>" . "          <li>Level 3</li>" . "          <li>Level 3, 2</li>" . "        </ol>" . "      </li>" . "    </ol>" . "  </li>" . "</ol>"),
    ),
    '#default_value' => variable_get('xbbcode_list_ol_default', 'hierarchy'),
  );
  $form['ol']['xbbcode_list_ol_hierarchy'] = array(
    '#type' => 'textfield',
    '#title' => t("Style hierarchy"),
    '#description' => t("Enter a comma-separated list of styles that will be used by nested lists. Valid styles are: upper-roman, lower-roman, numeric, upper-alpha, lower-alpha, none. Deeper levels will repeat the lowest level."),
    '#default_value' => variable_get('xbbcode_list_ol_hierarchy', 'numeric, lower-alpha, lower-roman'),
    '#autocomplete_path' => 'admin/settings/xbbcode/lists/autocomplete/ol',
  );
  return system_settings_form($form);
}
function xbbcode_list_admin_settings_validate($form_id, $values) {
  $valid_styles = array(
    'upper-alpha',
    'lower-alpha',
    'upper-roman',
    'lower-roman',
    'numeric',
  );
  $types = preg_split('/ *, */', $values['ol']['hierarchy']);
  foreach ($types as $type) {
    if (!in_array($type, $valid_styles)) {
      form_set_error('hierarchy', t("%type is not a valid style.", array(
        '%type' => $type,
      )));
    }
  }
}
function xbbcode_list_autocomplete($type, $string) {
  if ($type == 'ol') {
    $styles = array(
      'upper-alpha',
      'lower-alpha',
      'upper-roman',
      'lower-roman',
      'numeric',
    );
  }
  else {
    $styles = array();
  }
  $string = check_plain($string);
  foreach ($styles as $style) {
    if (preg_match("/^{$string}/", $style)) {
      $results[$style] = $style;
    }
  }
  print drupal_to_js($results);
  exit;
}