'ubrowser/main',
'title' => t('Browse taxonomy'),
'description' => t('Browse taxonomy like a file tree.'),
'callback' => 'ubrowser_display',
'access' => user_access('access content'),
'type' => MENU_CALLBACK,
);
// Search URL, displays results in the node div
$items[] = array(
'path' => 'ubrowser/nodesearch',
'title' => t('Search nodes'),
'description' => t('Display search results in the node box.'),
'callback' => 'ubrowser_nodesearch',
'access' => user_access('access content'),
'type' => MENU_CALLBACK,
);
// Let admin browse their content with uBrowser
$items[] = array(
'path' => 'admin/content/ubrowser',
'title' => t('Category browser'),
'description' => t('Browse nodes in your vocabularies using uBrowser.'),
'callback' => 'ubrowser_admin',
'access' => user_access('administer taxonomy'),
'type' => MENU_NORMAL_ITEM,
);
}
else {
drupal_add_css(drupal_get_path('module', 'ubrowser') .'/ubrowser.css');
if (is_numeric(arg(2))) {
// URL to display nodes in the node div
$items[] = array(
'path' => 'ubrowser/nodes/'. arg(2),
'title' => t('Display nodes'),
'description' => t('Display the child nodes of a taxonomy term.'),
'callback' => 'ubrowser_nodes',
'callback arguments' => array(arg(2), arg(3)),
'access' => user_access('access content'),
'type' => MENU_CALLBACK,
);
}
}
return $items;
}
/*******************************************************************************
* Callback Functions, Forms, and Tables
******************************************************************************/
/**
* Allow admin to build a uBrowser and browse their content with it.
*/
function ubrowser_admin() {
$output = '
'. t('uBrowser allows you to browse the content of your site '
.'by taxonomy vocabulary. Use the form to build uBrowser here. The '
.'textarea beneath the uBrowser will display the PHP to put the '
.'browser on a page in your site.') .'
'. t('PHP to build this uBrowser on a page:') .' '
.'
';
return $output;
}
/**
* Return the HTML to display the uBrowser inside a div.
*/
function ubrowser_display($settings = NULL) {
if ($settings === NULL && (empty($_POST) || !isset($_POST['div']))) {
drupal_goto('');
}
/**
* List of settings array keys and values:
* div = CSS selector of the div in which the uBrowser should display.
* class = Class to add to the div when uBrowser is loaded and remove when
* uBrowser is closed.
* vid = Vocabulary ID the uBrowser should browse.
* nids = String true or false to display node IDs in the node select box.
* filter = Comma delimeted string of node types to display.
* search = String true or false to display a node search form.
* close = String true or false to display a close button that wipes the div.
* view = String true or false to display a view button that browses
* to the selected node.
* window = String current or new for which window to view nodes in.
* categ = String of text to replace 'category' in displays, or leave blank.
* nodesg = String of text to replace 'node' in displays, or leave blank.
* nodepl = String of text to replace 'nodes' in displays, or leave blank.
* select = String of Javascript to execute on the select button
* (not displayed if no Javascript is set).
* multi = String true or false to allow users to select multiple nodes.
*/
if ($settings === NULL) {
$settings = array(
'div' => $_POST['div'],
'class' => $_POST['class'],
'vid' => intval($_POST['vid']),
'nids' => (($_POST['nids'] == 'true') ? '' : '/no_nids'),
'filter' => $_POST['filter'],
'search' => $_POST['search'],
'close' => $_POST['close'],
'view' => $_POST['view'],
'window' => (($_POST['window'] == 'new') ? 'new' : 'current'),
'categ' => ((strlen($_POST['categ']) > 0) ? $_POST['categ'] : 'category'),
'nodesg' => ((strlen($_POST['nodesg']) > 0) ? $_POST['nodesg'] : 'node'),
'nodepl' => ((strlen($_POST['nodepl']) > 0) ? $_POST['nodepl'] : 'nodes'),
'select' => $_POST['select'],
'multi' => (($_POST['multi'] == 'true') ? TRUE : FALSE),
);
$return_output = FALSE;
}
else {
if ($settings['nids'] == 'false') {
$settings['nids'] = '/no_nids';
}
else {
$settings['nids'] = '';
}
if (is_null($settings['categ']) || strlen($settings['categ']) == 0) {
$settings['categ'] = 'category';
}
if (is_null($settings['nodesg']) || strlen($settings['nodesg']) == 0) {
$settings['nodesg'] = 'node';
}
if (is_null($settings['nodepl']) || strlen($settings['nodepl']) == 0) {
$settings['nodepl'] = 'nodes';
}
$return_output = TRUE;
}
if ($settings['vid'] > 0) {
$tree = taxonomy_get_tree($settings['vid']);
$options = array();
if ($tree && (count($tree) > 1)) {
foreach ($tree as $term) {
$options[$term->tid] = str_repeat('-', $term->depth) . $term->name;
}
}
if (count($options) == 0) {
$options[0] = t('No terms found.');
}
}
// Get the appropriate forms into variables.
$term_select_form = drupal_get_form('ubrowser_tree_form', $options, $settings);
$node_select_form = drupal_get_form('ubrowser_nodes_form', NULL, $settings['categ'], $settings['nodesg'], $settings['multi']);
$search_form = '';
$actions_form = '';
if ($settings['search'] == 'true') {
$search_form = drupal_get_form('ubrowser_node_search_form');
}
if (strlen($settings['select']) > 0 || $settings['view'] == 'true' || $settings['close'] == 'true') {
$actions_form = drupal_get_form('ubrowser_node_actions_form', $settings);
}
// Output the table with appropriate classes and IDs for uBrowser and the CSS.
$output = '
'
.'
'. $term_select_form .'
'
.'
'. $node_select_form .'
'
.'
'
.'
'. $search_form .'
'
.'
'. $actions_form .'
'
.'
';
if ($return_output) {
return $output;
}
print $output;
exit();
}
/**
* Create the form for the term select box; also stores the widget settings.
*/
function ubrowser_tree_form($options, $settings = NULL) {
if (strlen($settings['categ']) > 0) {
$category = $settings['categ'];
}
else {
$category = 'category';
}
$form['tid'] = array(
'#type' => 'select',
'#title' => t('Select a !category', array('!category' => $category)),
'#size' => 10,
'#options' => $options,
'#attributes' => array('onchange' => "load_node_select(this.value, '". base_path() ."');"),
);
/**
* Save the settings array as hidden input fields in the uBrowser form.
* Settings are accessed by ID for different onclick actions:
* $('#edit-ub-key').val(); // Get the value of settings key using jQuery.
*/
if (!is_null($settings)) {
foreach ($settings as $key => $value) {
$form['settings']['ub-'. $key] = array(
'#type' => 'hidden',
'#value' => $value,
);
}
}
return $form;
}
/**
* Return the HTML for the node select box.
*/
function ubrowser_nodes($tid, $nids) {
if ($_POST['multi'] == 'true' || $_POST['multi'] == '1') {
$multi = TRUE;
}
else {
$multi = FALSE;
}
if (isset($_POST['filter'])) {
$filter = $_POST['filter'];
}
else {
$filter = NULL;
}
if (strlen($_POST['categ']) > 0) {
$category = $_POST['categ'];
}
else {
$category = 'category';
}
if (strlen($_POST['nodesg']) > 0) {
$nodesg = $_POST['nodesg'];
}
else {
$nodesg = 'node';
}
if (strlen($_POST['nodepl']) > 0) {
$nodepl = $_POST['nodepl'];
}
else {
$nodepl = 'nodes';
}
if ($tid == 0) {
$options = array(0 => t('Select a !category...'), array('!category' => $category));
}
else {
$result = _ubrowser_select_nodes(array($tid), $filter);
$options = array(0 => t('!Category contains !count !nodes!punctuation',
array('!Category' => ucfirst($category),
'!count' => db_num_rows($result),
'!nodes' => ((db_num_rows($result) == 1) ? $nodesg : $nodepl),
'!punctuation' => ((db_num_rows($result) == 0) ? '.' : ':'))));
while($node = db_fetch_object($result)) {
if ($nids == 'no_nids') {
$options[$node->nid] = $node->title;
}
else {
$options[$node->nid] = '('. $node->nid .') '. $node->title;
}
}
}
$output = drupal_get_form('ubrowser_nodes_form', $options, $category, $nodesg, $multi);
print $output;
exit();
}
/**
* Create the form for the node select box.
*/
function ubrowser_nodes_form($options, $categ = 'category', $nodesg = 'node', $multi = FALSE) {
if ($options === NULL) {
$options = array(0 => t('Select a !category...', array('!category' => $categ)));
}
else {
foreach ($options as $nid => $title) {
if ($nid > 0) {
$result = db_query("SELECT dst FROM {url_alias} WHERE src = 'node/". $nid ."'");
if ($alias = db_fetch_object($result)) {
$url = $alias->dst;
}
else {
$url = 'node/'. $nid;
}
$form['unid-path-'. $nid] = array(
'#type' => 'hidden',
'#value' => $url,
);
}
}
}
$form['unid'] = array(
'#type' => 'select',
'#multiple' => $multi,
'#title' => t('Select a !nodesg', array('!nodesg' => $nodesg)),
'#size' => 10,
'#options' => $options,
);
return $form;
}
/**
* Perform a search for nodes and display the results in the node box.
*/
function ubrowser_nodesearch() {
$keys = check_plain($_POST['keys']);
$filter = check_plain($_POST['filter']);
$category = check_plain($_POST['categ']);
$nodesg = check_plain($_POST['nodesg']);
$nodepl = check_plain($_POST['nodepl']);
if (is_null($keys) || strlen($keys) < 3) {
print '';
exit();
}
if (strlen($filter) > 0) {
$filter = "'". str_replace(',', "','", $filter) ."'";
$results = _ubrowser_search($keys, 'node',
'INNER JOIN {node} n ON n.nid = i.sid',
"(n.type IN ($filter))");
}
else {
$results = _ubrowser_search($keys, 'node');
}
if (($j = count($results)) == 0) {
$options = array(
-1 => t('Search yielded no results for:'),
0 => $keys,
);
}
elseif ($j == 1) {
$options = array(0 => t('Search yielded 1 result:'));
$result = db_query("SELECT nid, title FROM {node} WHERE nid = %d", $results[0]->sid);
if ($node = db_fetch_object($result)) {
if ($_POST['nids'] == '/no_nids') {
$options[$node->nid] = $node->title;
}
else {
$options[$node->nid] = '('. $node->nid .') '. $node->title;
}
}
}
else {
$options = array(0 => t('Search yielded !count results:', array('!count' => $j)));
foreach($results as $result) {
$nid_array[] = $result->sid;
}
$result = db_query("SELECT nid, title FROM {node} WHERE nid IN (%s)", implode(',', $nid_array));
while ($node = db_fetch_object($result)) {
if ($_POST['nids'] == '/no_nids') {
$options[$node->nid] = $node->title;
}
else {
$options[$node->nid] = '('. $node->nid .') '. $node->title;
}
}
}
$output = drupal_get_form('ubrowser_nodes_form', $options, $category, $nodesg);
print $output;
exit();
}
/**
* Create the form for the node search box.
*/
function ubrowser_node_search_form() {
$form = array(
'#attributes' => array('onsubmit' => 'return ubrowser_search_submit();'),
);
$form['usearch_keys'] = array(
'#type' => 'textfield',
'#size' => 10,
);
$form['usearch_submit'] = array(
'#type' => 'button',
'#value' => t('Search'),
'#attributes' => array('onclick' => "return load_node_search('". base_path() ."');"),
);
return $form;
}
/**
* Theme the node search box.
*/
function theme_ubrowser_node_search_form($form) {
$output = '
'
.'
'. drupal_render($form['usearch_keys']) .'
'
.'
'. drupal_render($form['usearch_submit']) .'
'
.'
';
return $output;
}
/**
* Create the form to display the actions buttons:
* view = Browses to the selected node.
* select = Executes the select Javascript using eval().
* close = Empties the uBrowser div and removes its class where applicable.
*/
function ubrowser_node_actions_form($settings) {
if ($settings['view'] == 'true') {
$form['uview'] = array(
'#type' => 'button',
'#value' => t('View'),
'#attributes' => array('onclick' => "return ubrowser_action_view('". base_path() ."');"),
);
}
if (strlen($settings['select']) > 0) {
$form['uselect'] = array(
'#type' => 'button',
'#value' => t('Select'),
'#attributes' => array('onclick' => 'return ubrowser_action_select();'),
);
}
if ($settings['close'] == 'true') {
$form['uclose'] = array(
'#type' => 'button',
'#value' => t('Close'),
'#attributes' => array('onclick' => 'return ubrowser_action_close();'),
);
}
return $form;
}
function theme_ubrowser_node_actions_form($form) {
$output = '
'
.'
'. drupal_render($form) .'
'
.'
';
return $output;
}
/*******************************************************************************
* Module and Helper Functions
******************************************************************************/
/**
* Return the HTML for a uBrowser populated div.
*
* @param $settings
* Associate array with the keys that define settings for uBrowser... see
* ubrowser_button() for a complete list.
* @return
* A string containing the HTML of the uBrowser div.
*/
function ubrowser($settings, $id = 'ubrowser') {
drupal_add_css(drupal_get_path('module', 'ubrowser') .'/ubrowser.css');
drupal_add_js(drupal_get_path('module', 'ubrowser') .'/ubrowser.js', 'module');
$settings = ubrowser_check_settings($settings);
$output = '
'
. ubrowser_display($settings) .'
';
return $output;
}
/**
* Return the HTML for an empty uBrowser div.
*
* @param $id
* The ID of the generated div.
* @param $message
* The message to display in the div before loading uBrowser. Defaults to
* uBrowser, but can be set to NULL to display nothing.
* @param $class
* An optional class you can set for the div.
* @return
* A string containing the HTML of the div.
*/
function ubrowser_div($id = 'ubrowser', $message = 'uBrowser', $class = 'ubrowser-div') {
if ($message !== NULL) {
$message = ''. $message .'';
}
if ($class !== NULL) {
$class = ' class="'. $class .'"';
}
drupal_add_css(drupal_get_path('module', 'ubrowser') .'/ubrowser.css');
drupal_add_js(drupal_get_path('module', 'ubrowser') .'/ubrowser.js', 'module');
return '
'. $message .'
';
}
/**
* Return the HTML for a button to display uBrowser in a div.
*
* I pondered how to make this work. In the end I decided to just put the
* Javascript in the button element itself. An alternative was to write a
* function out in the page and call it with a button click, but since this is
* all transparent, I'm going to uglify the HTML and leave it like it is.
*
* @param $value
* Text displayed on the button.
* @param $settings
* Associate array with the following keys that define settings for uBrowser:
* - div = CSS selector of the div in which the uBrowser should display.
* - class = Class to add to the div when uBrowser is loaded and remove when
* uBrowser is closed.
* - vid = Vocabulary ID the uBrowser should browse.
* - nids = String true or false to display node IDs in the node select box.
* - filter = Comma delimeted string of node types to display.
* - search = String true or false to display a node search form.
* - close = String true or false to display a close button that wipes the div.
* - view = String true or false to display a view button that browses
* to the selected node.
* - window = String current or new for which window to view nodes in.
* - categ = String of text to replace 'category' in displays, or leave blank.
* - nodesg = String of text to replace 'node' in displays, or leave blank.
* - nodepl = String of text to replace 'nodes' in displays, or leave blank.
* - select = String of Javascript to execute on the select button, not
* displayed if no value is set.
* - multi = String true or false to allow users to select multiple nodes.
* @param $name
* Optional name of the button.
* @param $id
* Optional id of the button.
* @return
* A string containing the HTML of the button.
*/
function ubrowser_button($value, $settings, $name = NULL, $id = NULL) {
$value = str_replace('"', '', $value);
if (strlen($value) == 0) {
$value = t('Display uBrowser');
}
if ($name !== NULL) {
$name = ' name="'. $name .'"';
}
if ($id !== NULL) {
$id = ' id="'. $id .'"';
}
drupal_add_css(drupal_get_path('module', 'ubrowser') .'/ubrowser.css');
drupal_add_js(drupal_get_path('module', 'ubrowser') .'/ubrowser.js', 'module');
$js_settings = str_replace('"', "'", drupal_to_js((object) $settings));
$output = '';
return $output;
}
/**
* Return the settings array with any ommitted settings set to defaults.
*
* @param $settings
* The settings array. See ubrowser_button() for available keys.
* @return
* The settings array with all ommitted settings set to their defaults.
*/
function ubrowser_check_settings($settings) {
$defaults = array(
'class' => '',
'nids' => '',
'filter' => '',
'search' => 'false',
'close' => 'false',
'view' => 'false',
'select' => '',
'multi' => 'false',
);
foreach($defaults as $key => $value) {
if (!array_key_exists($key, $settings)) {
$settings[$key] = $value;
}
}
return $settings;
}
/**
* Display a form that lets you build and display uBrowser on the fly.
*
* ubrowser_builder() lets you print a form to a page that can be used for
* custom building of uBrowsers. This is used from ubrowser_admin() to display
* the form at admin/content/browse.
*
* @param $settings
* A settings array that specifies what to set as default settings and what
* to display as options on the form. The following keys should either be
* set to TRUE, meaning they will be displayed on the form, or to an actual
* value to be used as the default value:
* - div = MUST be set, cannot be TRUE. Use a CSS selector for the div the
* custom built uBrowser will populate.
* - class = MUST be set, cannot be TRUE. The name of the class to add to
* the uBrowser div when it's loaded.
* - vid = TRUE to display a select box of vocabularies, otherwise specify
* the vocabulary ID this uBrowser must use.
* - nids = TRUE to display a checkbox for displaying node IDs, otherwise
* specify the string true or false.
* - search = TRUE to display a checkbox for displaying the search form,
* otherwise specify the string true or false.
* - view = TRUE to display a checkbox for displaying the view button,
* otherwise specify the string true or false.
* - window = TRUE to display a checkbox for choosing the view target window,
* otherwise specify the string new or current.
* - close = TRUE to display a checkbox for displaying the close button,
* otherwise specify the string true or false.
* - multi = TRUE to display a checkbox for displaying the multi select box,
* otherwise specify the string true or false.
* - filter = TRUE to display a set of checkboxes to filter displayed nodes by
* node type; only shows node types associated with current
* vocabularies. Alternately, specify a comma delimited string
* of node types to filter by default.
* - select = TRUE to display a textfield for entering Javascript for the
* select button, otherwise specify an empty string to not show
* a select button or a string of Javascript to execute.
* - nodesg = TRUE to display a textfield for entering the replacement text
* for the word 'node' in uBrowser displays. May be a string
* for the default replacement, or may be left unset for 'node'.
* - nodepl = TRUE to display a textfield for entering the replacement text
* for the word 'nodes' in uBrowser displays. May be a string
* for the default replacement, or may be left unset for 'nodes'.
* - code = MUST be either not set (to not display code) or set to the
* CSS selector of a textarea to populate with the PHP code to
* reproduce the built uBrowser. I can't imagine anyone else
* using this but figured it should be documented.
* - display = Optional, replacement text for the "Display uBrowser" button.
*/
function ubrowser_builder($settings) {
$form['ubb-div'] = array(
'#type' => 'hidden',
'#value' => $settings['div'],
);
// Add the vocabulary select box
if ($settings['vid'] === TRUE) {
$vocabs = taxonomy_get_vocabularies();
$options = array();
foreach($vocabs as $vocab) {
$options[$vocab->vid] = $vocab->name;
}
$form['ubb-vid'] = array(
'#type' => 'select',
'#title' => t('Vocabulary'),
'#description' => t('Select which vocabulary to browse.'),
'#options' => $options,
);
}
else {
$form['ubb-vid'] = array(
'#type' => 'hidden',
'#value' => $settings['vid'],
);
}
// Add the node type selection boxes
$form['filter-options'] = array(
'#type' => 'fieldset',
'#title' => t('Filter by node type'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
if ($settings['filter'] === TRUE) {
$options = array();
$result = db_query("SELECT DISTINCT type FROM {vocabulary_node_types}");
while ($type = db_fetch_object($result)) {
$options[$type->type] = $type->type;
}
$form['filter-options']['ubb-filter'] = array(
'#type' => 'checkboxes',
'#title' => t('Filter results for the following node types'),
'#description' => t('Selecting none will display all nodes.'),
'#options' => $options,
'#prefix' => '',
'#suffix' => '',
);
}
else {
$form['filter-options']['ubb-filter-desc'] = array(
'#value' => '