<?php
// $Id: distributor.module,v 1.12 2005/04/02 18:26:40 codemonkeyx Exp $
/**
Distributor Module - an easy to use intergrated distributor management module.
The distributor module allows for distributors to be organized and displayed in
a cenrtalized location. In essence it is a specialized taxonomy display
module with some specific features that make it sutible for distributors.
@author Nicholas Young-Soares
@package module_distributor
@defgroup module_distributor an easy to use intergrated distributor management module.
@{
**/
/**
Hook Block - displays the latest distributors list in a block.
@param op the operation to be preformed. (default="list")
@param delta the block to be displayed. (default=0)
@return an array containin the block output.
**/
function distributor_block($op = "list", $delta = 0, $edit = array()) {
if ($op == "list") {
$blocks[0]["info"] = t("Latest Distributors");
return $blocks;
}
elseif ($op == "view" && user_access("access content")) {
$content = module_invoke('node', 'title_list', distributor_get_latest(variable_get('distributor_recent_block', '5')), "");
if ($content) {
$content .= theme("more_info", l(t("more"), "distributor", array("title" => t("Read more distributors."))));
}
$blocks["subject"] = t(variable_get('distributor_block_title', t("Latest Distributors")));
$blocks["content"] = $content;
return $blocks;
}
elseif ($op == "configure" && $delta == 0) {
$form = form_textfield("Block Title", "distributor_block_title", variable_get("distributor_block_title", t("Latest Distributors")), 35, 255, t("Title of the Distributors block."));
$form .= form_select(t('Recent Distributors to Display'), 'distributor_recent_block', variable_get('distributor_recent_block', '5'), drupal_map_assoc(array(5, 10, 15, 20)), t("Sets the number of recent distributors that will be displayed in the Recent Distributors block."));
return $form;
}
elseif ($op == "save" && $delta == 0) {
variable_set('distributor_recent_block', $edit['distributor_recent_block']);
variable_set('distributor_block_title', $edit['distributor_block_title']);
}
}
/**
Hook Help - displays help and general information about the module.
@param section specifies the section to display help for.
@return a formated string containing the help output.
**/
function distributor_help($section) {
global $base_url;
$output = '';
switch ($section) {
case 'admin/help#distributor':
case 'admin/modules#description':
$output = t('Allow users to view nodes of multiple types in a central location.');
break;
}
return $output;
}
/**
Hook Link - returns links to the distributor module.
@param type specifies the type of link to display. (page or admin)
@param node
@return an array of links.
**/
function distributor_link($type, $node = 0) {
$links = array();
if ($type == 'page' && user_access('access content')) {
$links[] = l(t(variable_get('distributor_title', 'distributors')), 'distributor', array('title' => t('Distributors')));
}
return $links;
}
/**
Hook Menu - sets up distributor entries in the main menu..
@return an array of menu items.
**/
function distributor_menu($may_cache) {
$items = array();
$items[] = array('path' => 'distributor', 'title' => t('Distributors'), 'callback' => 'distributor_page', 'access' => user_access("access content"), 'type' => MENU_CALLBACK);
return $items;
}
/**
Hook Settings - admin settings for the distributor module.
@return a formatted settings form.
**/
function distributor_settings() {
$vocabularies = module_invoke('taxonomy', 'get_vocabularies');
if (is_array($vocabularies) && count($vocabularies) > 0) {
foreach ($vocabularies as $vocabulary) {
$select[$vocabulary->vid] = $vocabulary->name;
}
}
$output = form_select(t('Distributor Vocabularies'), 'distributor_vocab', variable_get('distributor_vocab', array()), $select, t('Select the vocabularies which contain the Distributor categories. All the vocabularies you select here will show up on the Distributor index.'), '', 1);
$output .= form_textfield('Overview Title', 'distributor_title', variable_get('distributor_title', t('Distributors')), 35, 255, t('Title of the Distributors box.'));
$output .= form_select(t('Index Depth'), 'distributor_index_depth', variable_get('distributor_index_depth', 0), array(0 => "All Terms", 1 => "1", 2 => "2", 3 => "3", 4 => "4", 5 => "5", 6 => "6"), t("Defines how many levels of terms should be displayed on any given distributor index page. For example, if you select 1 then only one level of the Distributor index tree will be displayed at a time."));
$recent_group = form_radios(t('Recent Distributors Box'), 'distributor_recent_box_enable', variable_get('distributor_recent_box_enable', 1), array(t('Disabled'), t('Enabled')), t('Enables or Disables the recent distributors box on the distributor index page.'), false);
$recent_group .= form_textfield('Box Title', 'distributor_recent_box_title', variable_get('distributor_recent_box_title', t('Latest Distributors')), 35, 255, t('Title of the Recent Distributors Box on the Distributor index page.'));
$recent_group .= form_select(t('Distributors to Display'), 'distributor_recent_display', variable_get('distributor_recent_display', '5'), array(5 => "5", 10 => "10", 15 => "15"), t("Sets the number of recent distributors that will be displayed in the Recent Distributors box. (0 = not displayed)."));
$output .= form_group(t('Recent Box Settings'), $recent_group);
return $output;
}
/**
Hook Page - displays the main distributor page.
@return null.
**/
function distributor_page() {
$body = "";
if (arg(1) == "feed") {
module_invoke('node', 'feed', module_invoke('taxonomy', 'select_nodes', distributor_get_distributor_terms(), 'or', 0, FALSE));
}
else {
if (arg(1) != NULL) {
$breadcrumb = drupal_get_breadcrumb();
$term = distributor_build_breadcrumbs($breadcrumb);
drupal_set_breadcrumb($breadcrumb);
if ($term != NULL) {
$content = distributor_index($term->tid);
if ($content != '') {
$body = theme('box', $term->name , $content);
}
// taking this out. why would i want to use my children's terms?
// we'll only print nodes from using my current terms
//$terms = array_merge(array($term->tid), array_map('_distributor_get_tid_from_term', module_invoke('taxonomy', 'get_children', $term->tid)));
// changed the selected term
print theme('page', $body . module_invoke('taxonomy', 'render_nodes', module_invoke('taxonomy', 'select_nodes', array($term->tid))));
}
}
else {
$body = '';
if (variable_get('distributor_recent_box_enable', 1)) {
$body = theme('box', variable_get('distributor_recent_box_title', t('Latest Distributors')), module_invoke('node', 'title_list', distributor_get_latest(variable_get('distributor_recent_display', '5')), '') . theme('more_info', l("<img src=\"misc/xml.png\" alt=\"XML Feed\" \>", 'distributor/feed')));
}
$content = distributor_index();
if ($content != '') {
print theme('page', $body . theme('box', t('Distributors'), $content));
}
}
}
}
/**
Constructs a url from the current url arguments list.
@return a string containing a formated URL.
**/
function distributor_get_current_url() {
$arg_index = 1;
$url = arg(0);
while ($argument = arg($arg_index)) {
$url .= '/'. urlencode($argument);
$arg_index++;
}
return $url;
}
/**
Constructs the distributor index page, using theme functions.
@return a string containing the output ready for display.
**/
function distributor_index($tid = 0) {
$output = "";
$vocabularies = distributor_get_vocabularies();
foreach ($vocabularies as $vocab) {
$max_depth = variable_get('distributor_index_depth', 0);
$vocab_tree = module_invoke('taxonomy', 'get_tree', $vocab->vid, $tid, -1, ($max_depth <= 0) ? NULL : $max_depth);
$content = '';
while (current($vocab_tree) != NULL) {
$content .= distributor_build_index($vocab_tree, distributor_get_current_url());
}
if ($content != '') {
$output .= theme('distributor_index', $vocab->name, $content);
}
}
return $output;
}
/**
Recursivly traverses the term tree to construct the index.
@return string the output for this tree.
**/
function distributor_build_index(&$tree, $parent_url) {
$output = '';
if ($tree == array()) {
return '';
}
do {
$cur = current($tree);
$nex = next($tree);
if ($nex === false) {
$next_depth = -1;
}
else {
$next_depth = $nex->depth;
}
$cur->link = $parent_url . '/' . urlencode(strtolower(trim($cur->name)));
$cur->children = '';
if ($next_depth > $cur->depth) {
$cur->children = distributor_build_index($tree, $cur->link);
// sync $next_depth, because 'next item' may be shoved forward
// Thanks for the patch Roderik.
$nex = current($tree);
if ($nex === false) {
$next_depth = -1;
}
else {
$next_depth = $nex->depth;
}
}
$cur->count = module_invoke('taxonomy', 'term_count_nodes', ($cur->tid));
$output .= theme('distributor_index_item', $cur);
}while ($cur->depth == $next_depth);
return theme('distributor_list', $output);
}
/**
Gets all the vocabularies that are associated with the distributor module.
@return array the vocabularies.
**/
function distributor_get_vocabularies() {
$allvocabularies = module_invoke('taxonomy', 'get_vocabularies');
$distributor_vocabs = variable_get('distributor_vocab', array());
$vocabularies = array();
foreach ($distributor_vocabs as $vocab) {
$vocabularies[] = $allvocabularies[$vocab];
}
return $vocabularies;
}
/**
Get all the terms associated with Distributors.
@return an array of unique term ids.
**/
function distributor_get_distributor_terms() {
$vocabs = distributor_get_vocabularies();
$tids = array();
foreach ($vocabs as $vocab) {
$tids = array_merge($tids, distributor_tax_get_terms($vocab->vid));
}
return array_unique($tids);
}
/**
Get all the terms in a given vocabulary.
@return an array of unique term ids.
**/
function distributor_tax_get_terms($vid) {
$result = db_query("SELECT tid FROM {term_data} WHERE vid = %d", $vid);
$tids = array();
while ($term = db_fetch_array($result)) {
$tids[] = $term['tid'];
}
return array_unique($tids);
}
/**
Get the latest distributors
@return a database query result.
**/
function distributor_get_latest($count = 0) {
$tids = distributor_get_distributor_terms();
return distributor_select_nodes($tids, 'or', 0, FALSE, $count);
}
/**
* Finds all nodes that match selected taxonomy conditions.
* This is just a copy of taxonomy_select_nodes() but
* includes node title field in the selection.
* Is this useful or try to find a taxonomy function
* to achieve this?
*
* @param $tids
* An array of term IDs to match.
* @param $operator
* How to interpret multiple IDs in the array. Can be "or" or "and".
* @param $depth
* How many levels deep to traverse the taxonomy tree. Can be a nonnegative
* integer or "all".
* @param $pager
* Whether the nodes are to be used with a pager (the case on most Drupal
* pages) or not (in an XML feed, for example).
* @return
* A resource identifier pointing to the query results.
*/
function distributor_select_nodes($tids = array(), $operator = 'or', $depth = 0, $pager = TRUE, $count = 0) {
if (count($tids) > 0) {
// For each term ID, generate an array of descendant term IDs to the right depth.
$descendant_tids = array();
if ($depth === 'all') {
$depth = NULL;
}
foreach ($tids as $index => $tid) {
$term = module_invoke('taxonomy', 'get_term', $tid);
$tree = module_invoke('taxonomy', 'get_tree', $term->vid, $tid, -1, $depth);
$descendant_tids[] = array_merge(array($tid), array_map('_distributor_get_tid_from_term', $tree));
}
if ($operator == 'or') {
$str_tids = implode(',', call_user_func_array('array_merge', $descendant_tids));
$sql = 'SELECT n.nid, n.title, n.sticky, n.created FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid IN ('. $str_tids .') AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC';
$sql_count = 'SELECT COUNT(n.nid) FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid IN ('. $str_tids .') AND n.status = 1';
}
else {
$joins = '';
$wheres = '';
foreach ($descendant_tids as $index => $tids) {
$joins .= ' INNER JOIN {term_node} tn'. $index .' ON n.nid = tn'. $index .'.nid';
$wheres .= ' AND tn'. $index .'.tid IN ('. implode(',', $tids) .')';
}
$sql = 'n.nid, n.title, n.sticky, n.created FROM {node} n '. $joins .' WHERE n.status = 1 AND '. $wheres .' ORDER BY n.sticky DESC, n.created DESC';
$sql_count = 'SELECT COUNT(n.nid) FROM {node} n '. $joins .' WHERE n.status = 1 AND '. $wheres;
}
if ($pager && ($count > 0)) {
$result = pager_query(db_rewrite_sql($sql), variable_get('default_nodes_main', 10) , 0, db_rewrite_sql($sql_count));
}
else {
$count = ($count > 0) ? $count : 15;
$result = db_query_range(db_rewrite_sql($sql), 0, $count);
}
}
return $result;
}
/**
Builds a breadcrumb list.
@param breadcrumb a reference to the breadcrumb array. New items will be appending to this array.
@return returns a term object if the last item in the url is a term, otherwise returns NULL.
**/
function distributor_build_breadcrumbs(&$breadcrumb) {
if (arg(1) != NULL) {
$i = 1;
$url = 'distributor';
$breadcrumb[] = l(ucwords(t('Distributors')), $url);
while (arg($i) != NULL) {
$last_term = urldecode(arg($i));
$url = $url . '/' . urlencode($last_term);
$breadcrumb[] = l(ucwords($last_term), $url);
$i++;
}
$term = current(module_invoke('taxonomy', 'get_term_by_name', $last_term));
return $term;
}
return NULL;
}
/**
Helper function for array map purposes.
@param term the term object from which the tid will be extracted.
@return the tid member of $term.
**/
function _distributor_get_tid_from_term($term) {
return $term->tid;
}
/** @} End of the module_distributor group **/
/**
@addtogroup theme_system
Distributor module specific theme functions.
@{
**/
/**
Controls the output of the rendered index list.
@return string the output for the index list.
**/
function theme_distributor_index(&$name, &$index_list) {
if ($index_list != "") {
return "<div class=\"item-list\">\n$index_list\n</div>\n";
}
return "";
}
/**
Displays a single one level list. Called for each group of items at the same depth.
@return string the output for this list.
**/
function theme_distributor_list(&$output) {
if ($output != '') {
return "<ul>". $output ."</ul>\n";
}
return '';
}
/**
Displays a single index item.
@return string the output for this item.
**/
function theme_distributor_index_item(&$term) {
$description = ($term->description != '') ? "<p class=\"distributor-desc\">". $term->description ."</p>" : '';
if ($term->count > 0) {
return "<li ><div class=\"distributor-title\">". l($term->name, $term->link) ."</div>". $description.$term->children ."</li>";
}
else {
return "<li><div class=\"distributor-title\">". $term->name ." </div>". $description.$term->children ."</li>";
}
}
/**
Displays more information content, suck as "more" links, and
feed images.
@return formatted string containint the output.
**/
function theme_more_info($content) {
return "<div class=\"more-link\">". $content ."</div>";
}
/** @} End of addtogroup theme_system **/
?>