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;
}