The category module allows you to structure your site and to categorize content: you can create multiple containers (types of categorizations) that contain a tree of categories; you can assign content to your categories; and you can give your categories their own content (such as a description).
');
case 'admin/help#category':
return t('The category module allows you to structure your site and to categorize content: you can create multiple containers (types of categorizations) that contain a tree of categories; you can assign content to your categories; and you can give your categories their own content (such as a description).
');
case 'node/add#category-cat':
return t("Categories are used to structure your site, and to categorize content. You can create a category as the child of a container, or of another category. You can assign content to one or more categories.");
case 'node/add#category-cont':
return t("A container is usually the root of a category tree, but can also be created as the child of another container, or of a category. Containers are used for describing a particular way of classifying content.");
case 'admin/settings/category':
return t('Settings controlling the behaviour of categories and containers on this site. As well as settings for the category module itself, settings for other modules in the category package can also be configured here. Only global settings are controlled here: most settings are controlled on a per-container or per-category basis, and are instead configured on the add/edit category/container pages. See the categories page for actual categories and containers.
', array('%category' => url('admin/category')));
}
}
/**
* Implementation of hook_node_info().
*/
function category_node_info() {
$base_types = variable_get('category_base_nodetypes', array('category-cat' => 'category-cat', 'category-cont' => 'category-cont'));
$types_list = array();
if ($base_types['category-cont']) {
$types_list['category-cont'] = array('name' => t('container'), 'base' => 'category');
}
if ($base_types['category-cat']) {
$types_list['category-cat'] = array('name' => t('category'), 'base' => 'category');
}
return $types_list;
}
/**
* Implementation of hook_perm().
*/
function category_perm() {
$base_types = variable_get('category_base_nodetypes', array('category-cat' => 'category-cat', 'category-cont' => 'category-cont'));
$perms_list = array();
if ($base_types['category-cat']) {
$perms_list[] = 'create categories';
}
if ($base_types['category-cont']) {
$perms_list[] = 'create containers';
}
if ($base_types['category-cat'] || $base_types['category-cont']) {
$perms_list[] = 'edit all categories';
$perms_list[] = 'edit own categories';
}
$perms_list[] = 'administer categories';
return $perms_list;
}
/**
* Implementation of hook_init().
*
*/
function category_init() {
require_once dirname(drupal_get_filename('module', 'category')) . '/category.inc';
}
/**
* Implementation of hook_menu().
*/
function category_menu($may_cache) {
$items = array();
$base_types = variable_get('category_base_nodetypes', array('category-cat' => 'category-cat', 'category-cont' => 'category-cont'));
if ($may_cache) {
$items[] = array(
'path' => 'category',
'title' => t('categories'),
'callback' => 'category_category_page',
'access' => user_access('access content'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'category/export',
'callback' => 'category_export_page',
'access' => user_access('access content'),
'type' => MENU_CALLBACK);
$items[] = array(
'path' => 'admin/category',
'title' => t('categories'),
'callback' => 'category_admin',
'access' => user_access('administer categories'),
);
$items[] = array(
'path' => 'admin/category/list',
'title' => t('list'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items[] = array(
'path' => 'admin/category/list/container',
'title' => t('containers'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items[] = array(
'path' => 'admin/category/add',
'title' => t('add container'),
'callback' => 'category_admin',
'access' => user_access('administer categories'),
'type' => MENU_LOCAL_TASK,
'weight' => -6,
);
if ($base_types['category-cat']) {
$items[] = array(
'path' => 'node/add/category-cat',
'title' => t('category'),
'access' => _category_privileged('create categories'),
);
}
if ($base_types['category-cont']) {
$items[] = array(
'path' => 'node/add/category-cont',
'title' => t('container'),
'access' => _category_privileged('create containers'),
);
}
$items[] = array('path' => 'category/autocomplete',
'title' => t('autocomplete category'),
'callback' => 'category_autocomplete',
'access' => user_access('access content'),
'type' => MENU_CALLBACK,
);
$items[] = array('path' => 'category/activeselect',
'title' => t('activeselect category'),
'callback' => 'category_activeselect',
'access' => user_access('access content'),
'type' => MENU_CALLBACK,
);
$items[] = array('path' => 'category/wrapper',
'title' => t('category wrappers'),
'callback' => 'category_wrapper',
'access' => user_access('administer site configuration'),
'type' => MENU_CALLBACK,
);
}
else {
if (arg(0) == 'admin' && arg(1) == 'category' && is_numeric(arg(2))) {
$nid = arg(2);
$node = node_load($nid);
$items[] = array(
'path' => 'admin/category/' . $nid,
'title' => $node->admin_title,
'callback' => 'category_admin',
'access' => user_access('administer categories'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'admin/category/' . $nid . '/list',
'title' => t('list'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items[] = array(
'path' => 'admin/category/' . $nid . '/list/category',
'title' => t('categories'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items[] = array(
'path' => 'admin/category/' . $nid . '/add',
'title' => t('add category'),
'callback' => 'category_admin',
'access' => user_access('administer categories'),
'type' => MENU_LOCAL_TASK,
);
}
elseif (arg(0) == 'node' && is_numeric(arg(1))) {
$nid = arg(1);
$is_cat = category_is_cat_or_cont($nid);
if ($is_cat) {
$items[] = array(
'path' => "node/$nid/feed",
'title' => t('feed'),
'callback' => 'category_feed',
'type' => MENU_CALLBACK,
);
}
}
}
return $items;
}
/**
* Implementation of hook_access().
*/
function category_access($op, $node) {
global $user;
if ($op == 'create') {
$type = $node;
if ($type == 'category-cont') {
return _category_privileged('create containers');
}
else {
return _category_privileged('create categories');
}
}
if ($op == 'update') {
// Only registered users can update categories. Given the nature
// of the category module this is considered to be a good/safe idea.
// One can only update a category page if there are no suggested updates
// of that page waiting for approval. That is, only updates that
// don't overwrite the current or pending information are allowed.
if ((_category_privileged('edit all') && !$node->moderate) || ($node->uid == $user->uid && user_access('edit own categories'))) {
return TRUE;
}
else {
// do nothing. node-access() will determine further access
}
}
}
/**
* Implementation of hook_link().
*
* This hook is extended with $type = 'categories' to allow themes to
* print lists of categories associated with a node. Themes can print category
* links with:
*
* if (module_exist('category')) {
* $this->links(category_link('categories', $node));
* }
*/
function category_link($type, $node = NULL, $main = NULL) {
$links = array();
if ($type == 'node' && isset($node->parents)) {
if (!$main && ($node->type != 'category-cat' || $node->hierarchy)) {
if (_category_privileged('create categories')) {
$links[] = l(t('add child category'), "node/add/category-cat/parent/$node->nid");
}
if (_category_privileged('create containers')) {
$links[] = l(t('add child container'), "node/add/category-cont/parent/$node->nid");
}
}
}
if (($type == 'categories') && $node != NULL) {
$links = array();
if (isset($node->category) && is_array($node->category)) {
foreach ($node->category as $category) {
if (!module_exist('category_display') || ($category->cid && ($cat_node = node_load($category->cid)) && $cat_node->nodelinks)) {
$links[] = l($category->title, category_category_path($category), array('rel' => 'tag', 'title' => $category->description));
}
}
}
}
return $links;
}
/**
* Implementation of hook_settings().
*/
function category_settings() {
$form = array();
// select options
$distant = array(
'0' => t('None'),
'1' => t('One'),
'2' => t('Multiple'),
);
// Wrapper settings
$form['wrappers'] = array(
'#type' => 'fieldset',
'#title' => t('Wrapper install / uninstall settings'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
);
$book_status = category_get_wrapper_status('book');
$taxonomy_status = category_get_wrapper_status('taxonomy');
$form['wrappers']['book_wrapper'] = array(
'#type' => 'item',
'#title' => t('Book wrapper status'),
'#value' => theme('category_wrapper_status', 'book', $book_status),
);
$form['wrappers']['taxonomy_wrapper'] = array(
'#type' => 'item',
'#title' => t('Taxonomy wrapper status'),
'#value' => theme('category_wrapper_status', 'taxonomy', $taxonomy_status),
'#description' => ''. t('You can install and uninstall the taxonomy and book wrapper modules using the links below. It is very important that you have taxonomy or book (original or wrapper, whichever is installed) enabled on the %module-admin-page before performing an install or uninstall. Additionally, you should make sure that your web server has write permission on the file system, or the scripts may be denied access to copy and rename the necessary files.', array('%module-admin-page' => l(t('module administration page'), 'admin/modules'))). '
'. t('When performing an install, the scripts will rename your existing taxonomy or book module file to modulename.module.old. It will then copy the appropriate modulename.module.copyme file from the wrappers/ directory (in your category package) to the location where the old module file was, and will rename the copied file to modulename.module. The reverse will happen when performing an uninstall. The script will determine the correct location of all necessary files automatically, based on the existing locations of those files.'). '
'. t('After the operation that you invoke is completed, you will be returned to this page.'). '
',
);
// Node type settings
$form['nodetype'] = array(
'#type' => 'fieldset',
'#title' => t('Content type settings'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['nodetype']['category_allow_nodetypes'] = array(
'#type' => 'checkboxes',
'#title' => t('Allow other content types to be'),
'#default_value' => variable_get('category_allow_nodetypes', array('category-cat' => 0, 'category-cont' => 0)),
'#options' => array('category-cat' => t('Categories'), 'category-cont' => t('Containers')),
'#description' => t('Allows category or container behavior to be assigned to other content types. When enabled, each content type (except for category and container) receives a new setting allowing it to be a category or a container. When switched on for a particular content type, all nodes of that type receive the new behavior.')
);
$form['nodetype']['category_base_nodetypes'] = array(
'#type' => 'checkboxes',
'#title' => t('Provide these content types'),
'#default_value' => variable_get('category_base_nodetypes', array('category-cat' => 'category-cat', 'category-cont' => 'category-cont')),
'#options' => array('category-cat' => t('Category'), 'category-cont' => t('Container')),
'#description' => t('Provides a built-in content type for creating categories, and a built-in content type for creating containers. Do not disable either of these unless you have allowed other content types to be categories or containers, and you have set other content types to have category or container behavior; otherwise, you will have not be able to create categories or containers.')
);
// Distant parent settings
$form['distant'] = array(
'#type' => 'fieldset',
'#title' => t('Distant parent settings'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['distant']['category_distant_containers'] = array(
'#type' => 'radios',
'#title' => t('Number of parents that a container can have'),
'#default_value' => variable_get('category_distant_containers', 1),
'#options' => $distant,
'#description' => t('If set to more than zero, this allows your containers to select other containers, or categories, as distant parents. Changing this setting does not affect your existing containers; unless you change it from \'one\' or \'multiple\' to \'zero\', and you then manually update an individual container, in which case all distant parent relationships for that container will be lost. This setting does not affect distant parent relationships for categories: these are managed separately within each container.')
);
// Allow other modules to add additional settings.
$extra = module_invoke_all('category', 'settings');
if (isset($extra) && is_array($extra)) {
foreach ($extra as $key => $value) {
$form[$key] = $value;
}
}
$form['buttons']['#weight'] = 10;
return $form;
}
/**
* Implementation of hook_load().
*/
function category_load($node, $type = NULL) {
global $user;
$type = category_node_get_type($node, $type);
$is_cat = $type == 'category-cat';
$category = category_get_category($node->nid);
unset($category->cid);
unset($category->title);
if (!$is_cat) {
// Get all extra container info for container nodes.
$container = category_get_container($node->nid);
}
else {
// Get info about the parent container for category nodes.
$container = category_get_container($category->cnid);
$container->cnid = $container->cid;
}
if (!empty($container)) {
// Merge the container fields into the category object.
foreach ($container as $key => $value) {
$category->$key = $value;
}
}
unset($category->cid);
unset($category->title);
$parents = array();
if (!$is_cat) {
$category = (object)array_merge((array)$category, (array)$container);
$parent_list = category_get_parents($node->nid, 'cid', variable_get('category_distant_containers', 1));
foreach ($parent_list as $parent) {
$parents[] = $parent->cid;
}
}
else {
$parent_list = category_get_parents($node->nid, 'cid', $category->children_have_distant);
foreach ($parent_list as $parent) {
$parents[] = $parent->cid;
}
if ($category->has_relations) $category->relations = array_keys(category_get_related($node->nid));
if ($category->has_synonyms) $category->synonyms = category_get_synonyms($node->nid);
}
$category->parents = $parents;
if (!empty($parents)) {
$category->parent = $parents[0];
}
else {
$category->parent = 0;
}
return $category;
}
/**
* Implementation of hook_insert().
*/
function category_insert($node, $type = NULL) {
category_update($node, $type);
}
/**
* Implementation of hook_update().
*/
function category_update($node, $type = NULL) {
$node->cid = $node->nid;
$node->module = $node->module ? $node->module : 'category';
$type = category_node_get_type($node, $type);
$is_cat = $type == 'category-cat';
$data_exists = (db_num_rows(db_query('SELECT * FROM {category} WHERE cid = %d', $node->nid)) > 0);
if ($data_exists) {
db_query("UPDATE {category} SET cnid = %d, weight = %d, description = '%s', depth = %d WHERE cid = %d", $node->cnid, $node->weight, $node->description, $node->depth, $node->nid);
}
else {
db_query("INSERT INTO {category} (cid, cnid, description, weight, depth) VALUES (%d, %d, '%s', %d, %d)", $node->nid, $node->cnid, $node->description, $node->weight, $node->depth);
}
db_query('DELETE FROM {category_hierarchy} WHERE cid = %d', $node->nid);
if (!empty($node->parents) && (!is_array($node->parents) || isset($node->parents[0]))) {
if (!is_array($node->parents)) {
$node->parents = array($node->parents);
}
foreach ($node->parents as $key => $parent) {
if (isset($parent)) {
db_query('INSERT INTO {category_hierarchy} (cid, parent) VALUES (%d, %d)', $node->nid, $parent);
}
}
}
else {
if ($is_cat) {
db_query('INSERT INTO {category_hierarchy} (cid, parent) VALUES (%d, %d)', $node->nid, $node->cnid);
}
else {
db_query('INSERT INTO {category_hierarchy} (cid, parent) VALUES (%d, %d)', $node->nid, 0);
}
}
if (!$is_cat) {
if (empty($node->admin_title)) {
$node->admin_title = '';
}
$data_exists = (db_num_rows(db_query('SELECT * FROM {category_cont} WHERE cid = %d', $node->nid)) > 0);
if ($data_exists) {
db_query('UPDATE {category_cont} SET '. _category_container_update($node) .' WHERE cid = %d', $node->nid);
}
else {
db_query('INSERT INTO {category_cont} '. _category_container_insert($node, 1) .' VALUES '. _category_container_insert($node, 2));
}
db_query("DELETE FROM {category_cont_node_types} WHERE cid = %d", $node->nid);
if (isset($node->nodes) && is_array($node->nodes)) {
foreach ($node->nodes as $type => $value) {
if ($value) {
db_query("INSERT INTO {category_cont_node_types} (cid, type) VALUES (%d, '%s')", $node->nid, $type);
}
}
}
db_query("DELETE FROM {category_cont_distant} WHERE cid = %d", $node->nid);
if (isset($node->children_allowed_parents) && is_array($node->children_allowed_parents)) {
foreach ($node->children_allowed_parents as $key => $allowed_parent) {
if (isset($allowed_parent)) {
db_query("INSERT INTO {category_cont_distant} (cid, allowed_parent) VALUES (%d, '%s')", $node->nid, $allowed_parent);
}
}
}
}
else {
db_query('DELETE FROM {category_relation} WHERE cid1 = %d OR cid2 = %d', $node->nid, $node->nid);
if ($node->relations) {
foreach ($node->relations as $related_id) {
if ($related_id != 0) {
db_query('INSERT INTO {category_relation} (cid1, cid2) VALUES (%d, %d)', $node->nid, $related_id);
}
}
}
db_query('DELETE FROM {category_synonym} WHERE cid = %d', $node->nid);
if ($node->synonyms) {
$synonyms = $node->synonyms;
if (!is_array($node->synonyms)) {
$synonyms = explode("\n", str_replace("\r", '', $node->synonyms));
}
foreach ($synonyms as $synonym) {
if ($synonym) {
db_query("INSERT INTO {category_synonym} (cid, name) VALUES (%d, '%s')", $node->nid, chop($synonym));
}
}
}
}
}
/**
* Implementation of hook_delete().
*/
function category_delete(&$node, $type = NULL) {
$type = category_node_get_type($node, $type);
$is_cat = $type == 'category-cat';
db_query('DELETE FROM {category} WHERE cid = %d', $node->nid);
db_query('DELETE FROM {category_hierarchy} WHERE cid = %d', $node->nid);
if (!$is_cat) {
db_query('DELETE FROM {category_cont} WHERE cid = %d', $node->nid);
db_query("DELETE FROM {category_cont_node_types} WHERE cid = %d", $node->nid);
db_query("DELETE FROM {category_cont_distant} WHERE cid = %d OR allowed_parent = %d", $node->nid, $node->nid);
}
else {
category_select_nodes_cache($node->nid);
db_query('DELETE FROM {category_node} WHERE cid = %d', $node->nid);
db_query('DELETE FROM {category_relation} WHERE cid1 = %d OR cid2 = %d', $node->nid, $node->nid);
db_query('DELETE FROM {category_synonym} WHERE cid = %d', $node->nid);
}
}
/**
* Implementation of hook_form().
*/
function category_form(&$node) {
$parent_cont = arg(4);
$is_cat = $node->type == 'category-cat';
if (is_numeric($parent_cont)) {
$category = category_get_category($parent_cont);
$container = NULL;
if ($category->cnid) {
$container = category_get_container($category->cnid);
}
else {
$container = category_get_container($parent_cont);
}
$container->cnid = $container->cid;
unset($container->cid);
unset($container->title);
if ($is_cat) {
foreach ($container as $key => $value) {
$node->$key = $value;
}
}
$node->parent_cont = $parent_cont;
}
$form = category_get_form($is_cat, $node);
if (strpos($_GET['q'], 'node/add/category-cat/parent') !== FALSE) {
$form['destination'] = array(
'#type' => 'hidden',
'#value' => $_GET['q'],
);
}
return $form;
}
/**
* Implementation of hook_category_legacy().
*
*/
function category_category_legacy($op, &$items, $edit = NULL) {
switch ($op) {
case 'import_taxonomy_form':
case 'import_book_form':
$note = ''. t('Note:') .'';
unset($items['catinfo']['description']);
unset($items['catinfo']['cnid']);
unset($items['catinfo']['help']);
unset($items['catinfo']['admin_title']);
unset($items['catinfo']['weight']);
unset($items['catinfo']['depth']);
$items['catinfo']['parents']['#description'] .= '
'. t('%note this setting only affects containers. Categories retain the parents that they had as %former-self.', array('%note' => $note, '%former-self' => (($op == 'import_taxonomy_form') ? t('taxonomy terms') : t('book pages'))));
$items['catinfo']['depth_cont'] = array(
'#type' => 'weight',
'#title' => t('Depth of containers'),
'#default_value' => 0,
'#delta' => 10,
'#description' => t('The depth of child categories that a node listing reflects. Set this to a negative value to reflect an infinite depth. Although a container cannot be assigned nodes, it can still list nodes of child categories, if it has a depth that is not 0.'). '
'. t('%note this setting only affects containers, not their child categories.', array('%note' => $note)),
);
$items['catinfo']['depth_cats'] = array(
'#type' => 'weight',
'#title' => t('Depth of categories'),
'#default_value' => 0,
'#delta' => 10,
'#description' => t('Same as previous setting, except that this setting only affects categories, not containers.'),
);
if ($op == 'import_taxonomy_form') {
$items['filter'] = filter_form();
unset($items['catinfo']['nodes']);
unset($items['catinfo']['hierarchy']);
unset($items['catinfo']['has_relations']);
unset($items['catinfo']['tags']);
unset($items['catinfo']['multiple']);
unset($items['catinfo']['required']);
}
break;
case 'import_taxonomy_prepare':
case 'import_book_prepare':
$fields = array();
if ($op == 'import_taxonomy_prepare') {
$fields = array('has_synonyms', 'hidden_cont', 'parents', 'children_allowed_parents', 'format');
}
else {
$fields = array('nodes', 'hierarchy', 'has_relations', 'has_synonyms', 'tags', 'multiple', 'required', 'hidden_cont', 'parents', 'children_allowed_parents');
}
foreach ($items as $key => $item) {
foreach ($fields as $field) {
$items[$key][$field] = $edit[$field];
}
$items[$key]['depth'] = $edit['depth_cont'];
if ($op == 'import_taxonomy_prepare') {
foreach ($item['terms'] as $tid => $term) {
$items[$key]['terms'][$tid]['depth'] = $edit['depth_cats'];
$items[$key]['terms'][$tid]['format'] = $edit['format'];
}
if ($edit['description_target']) {
$items[$key]['body'] = $items[$key]['description'];
$items[$key]['description'] = '';
foreach ($item['terms'] as $tid => $term) {
$items[$key]['terms'][$tid]['body'] = $items[$key]['terms'][$tid]['description'];
$items[$key]['terms'][$tid]['description'] = '';
}
}
}
else {
foreach ($item['children'] as $tid => $term) {
$items[$key]['children'][$tid]['depth'] = $edit['depth_cats'];
}
}
}
break;
case 'export_taxonomy_prepare':
foreach ($items as $key => $item) {
if ($edit['description_target']) {
$items[$key]['description'] = $items[$key]['body'];
foreach ($item['cats'] as $tid => $term) {
$items[$key]['cats'][$tid]['description'] = $items[$key]['cats'][$tid]['body'];
}
}
}
break;
}
}
/**
* Implementation of hook_submit().
*/
function category_submit(&$node) {
$node->cid = $node->nid;
if (!isset($node->parents) || !is_array($node->parents)) {
$node->parents = array($node->parents);
}
if (!isset($node->parents[0])) {
if ($node->type == 'category-cat') {
$node->parents[0] = $node->parent = $node->cnid;
}
else {
unset($node->parents[0]);
$node->parent = 0;
}
}
else {
$node->parent = $node->parents[0];
}
if (!isset($node->nodes) || !is_array($node->nodes)) {
$node->nodes = array($node->nodes);
}
if (empty($node->nodes[0])) {
unset($node->nodes[0]);
}
}
/**
* Menu callback; dispatches to the proper category administration function.
*/
function category_admin() {
// Special case for our "add category" menu localtask. this covers
// the use of the "add category" LOCAL_TASK on a "view categories" page.
if (is_numeric(arg(2)) && arg(3) == 'add') {
drupal_goto('node/add/category-cat/parent/'. arg(2));
}
// Another special case for the "add container" menu localtask.
elseif (arg(2) == 'add') {
$destination = 'destination=admin/category';
drupal_goto('node/add/category-cont', $destination);
}
return category_overview();
}
/**
* Generates a tabular listing of administrative functions for
* containers and categories.
*/
function category_overview() {
drupal_set_html_head(theme('stylesheet_import', base_path() . drupal_get_path('module', 'category') .'/category.css'));
$cnid = arg(2);
$destination = drupal_get_destination();
$start_from = $_GET['page'] ? $_GET['page'] : 0;
$total_entries = 0; // total count for pager
$page_increment = 25; // number of rows per page
$displayed_count = 0; // number of rows shown
// Show all containers and their categories.
if (!$cnid) {
$colspan = 4;
$header = NULL;
if (variable_get('category_distant_containers', 1) > 0) {
$header = array(t('Name'), t('Types'), t('Parents'), array('data' => t('Operations'), 'colspan' => '2'));
$colspan = 5;
}
else {
$header = array(t('Name'), t('Types'), array('data' => t('Operations'), 'colspan' => '2'));
}
$containers = category_get_containers();
foreach ($containers as $container) {
$total_entries++; // we're counting all-totals, not displayed
if (($start_from && ($start_from * $page_increment) >= $total_entries) || ($displayed_count == $page_increment)) {
continue;
}
$types = array();
if (is_array($container->nodes)) {
foreach ($container->nodes as $key => $type) {
if ($type) {
$node_type = node_get_name($type);
$types[] = $node_type ? $node_type : $type;
}
}
}
$parents_list = category_get_parents($container->cid);
$parents = array();
$first_parent = true;
foreach ($parents_list as $parent) {
$attributes = array();
if ($first_parent) {
$attributes['class'] = 'category-first-parent';
$first_parent = false;
}
$parents[] = l(($parent->cnid ? $parent->title : $parent->admin_title), 'node/'. $parent->cid, $attributes);
}
$none = theme('placeholder', t('none'));
if ($colspan == 4) {
$rows[] = array(l($container->admin_title, "node/$container->cid"), (!empty($types) ? implode(', ', $types) : $none), l(t('edit container'), "node/$container->cid/edit", array(), $destination), l(t('list categories'), "admin/category/$container->cid"));
}
else {
$rows[] = array(l($container->admin_title, "node/$container->cid"), (!empty($types) ? implode(', ', $types) : $none), (!empty($parents) ? implode(', ', $parents) : $none), l(t('edit container'), "node/$container->cid/edit", array(), $destination), l(t('list categories'), "admin/category/$container->cid"));
}
$displayed_count++; // we're counting containers displayed
}
if (!$rows) {
$rows[] = array(array('data' => t('No containers available.'), 'colspan' => "$colspan", 'class' => 'message'));
}
$GLOBALS['pager_page_array'][] = $start_from; // FIXME
$GLOBALS['pager_total'][] = intval($total_entries / $page_increment) + 1; // FIXME
if ($total_entries >= $page_increment) {
$rows[] = array(array('data' => theme('pager', NULL, $page_increment), 'colspan' => "$colspan"));
}
}
// Show children of a particular node in the tree.
else {
$container = category_get_container($cnid);
$header = NULL;
$colspan = 2;
if ($container->children_have_distant) {
$header = array(t('Name'), t('Distant parents'), t('Operations'));
$colspan = 3;
}
else {
$header = array(t('Name'), t('Operations'));
}
$tree = category_get_tree($cnid,NULL, -1, 2);
$cats_nodepth = array();
foreach ($tree as $category) {
$total_entries++; // we're counting all-totals, not displayed
if (($start_from && ($start_from * $page_increment) >= $total_entries) || ($displayed_count == $page_increment)) {
continue;
}
if (!$category->depth) {
if (isset($cats_nodepth[$category->cid])) {
continue;
}
else {
$cats_nodepth[$category->cid] = TRUE;
}
}
$parents_list = category_get_parents($category->cid);
$parents = array();
$first_parent = true;
foreach ($parents_list as $parent) {
if ($parent->cid != $cnid && $parent->cnid != $cnid) {
$attributes = array();
if ($first_parent) {
$attributes['class'] = 'category-first-parent';
$first_parent = false;
}
$parents[] = l(($parent->cnid ? $parent->title : $parent->admin_title), 'node/'. $parent->cid, $attributes);
}
}
$none = theme('placeholder', t('none'));
if ($colspan == 2) {
$rows[] = array(_category_depth($category->depth) . ' ' . l($category->title, "node/$category->cid"), l(t('edit'), "node/$category->cid/edit", array(), $destination));
}
else {
$rows[] = array(_category_depth($category->depth) . ' ' . l($category->title, "node/$category->cid"), (!empty($parents) ? implode(', ', $parents) : $none), l(t('edit'), "node/$category->cid/edit", array(), $destination));
}
$displayed_count++; // we're counting categories displayed
}
if (!$rows) {
$rows[] = array(array('data' => t('No categories available.'), 'colspan' => '3'));
}
$GLOBALS['pager_page_array'][] = $start_from; // FIXME
$GLOBALS['pager_total'][] = intval($total_entries / $page_increment) + 1; // FIXME
if ($total_entries >= $page_increment) {
$rows[] = array(array('data' => theme('pager', NULL, $page_increment), 'colspan' => "$colspan"));
}
}
return theme('table', $header, $rows, array('id' => 'category'));
}
/**
* Implementation of hook_nodeapi().
*/
function category_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
switch ($op) {
case 'load':
$node->category = category_node_get_categories($node->nid);
if ($node->type != 'category-cat' && $node->type != 'category-cont' && category_is_cat_or_cont($node->nid)) {
$extra = category_load($node);
foreach ($extra as $key => $value) {
$node->$key = $value;
}
}
break;
case 'insert':
case 'update':
// Support for other node types
$cat_type = variable_get('category_nodeapi_'. $node->type, 'none');
if ($cat_type != 'none') {
category_submit($node);
category_update($node, $cat_type);
}
// Support for category_transform
$op = $_POST['op'];
$submit_values = array(
'insert' => t('Add to category outline'),
'update' => t('Update category outline'),
'delete' => t('Remove from category outline'),
);
$type = category_node_get_type($node, arg(2));
if (in_array($op, $submit_values)) {
switch ($op) {
case $submit_values['insert']:
case $submit_values['update']:
category_update($node, $type);
break;
case $submit_values['delete']:
category_delete($node, $type);
break;
}
}
// Save assigned node mappings
if (isset($node->category)) {
category_node_save($node);
}
break;
case 'delete':
category_node_delete($node->nid);
break;
case 'validate':
category_node_validate($node);
break;
case 'rss item':
return category_rss_item($node);
break;
case 'view':
if (!$teaser && category_is_cat_or_cont($node->nid)) {
$node->body = theme('category_view', $node);
}
break;
}
}
/**
* Menu callback; generates the RSS feed for all nodes associated with a
* category.
*/
function category_feed() {
$cid = arg(1);
if (is_numeric($cid)) {
$cat = category_get_category($cid);
if (!empty($cat)) {
$channel['link'] = url('node/'. $cid, NULL, NULL, TRUE);
$channel['title'] = variable_get('site_name', 'drupal') .' - '. $cat->title;
$channel['description'] = $cat->description;
if ($cat->depth < 0) {
$cat->depth = 'all';
}
$result = category_select_nodes(array($cid), 'or', $cat->depth, FALSE, TRUE);
node_feed($result, $channel);
}
}
}
/**
* Generate a form element for selecting categories from a container.
*/
function category_form_node($cnid, $value = 0, $help = NULL, $name = 'category') {
$container = category_get_container($cnid);
$help = ($help) ? $help : $container->help;
if ($container->required) {
$blank = 0;
}
else {
$blank = '<'. t('none') .'>';
}
return _category_node_select(check_plain($container->title), $value, $cnid, $help, intval($container->multiple), $blank);
}
/**
* Generate a form for selecting categories to associate with a node. Also
* creates a setting to toggle category/container behaviour per node type.
*/
function category_form_alter($form_id, &$form) {
$type = (isset($form['type']) && isset($form['type']['#value'])) ? $form['type']['#value'] : NULL;
$node = isset($form['#node']) ? $form['#node'] : NULL;
switch ($form_id) {
// node settings form
case $type .'_node_settings':
if ($type != 'category-cont') {
$allow_types = variable_get('category_allow_nodetypes', array('category-cat' => 0, 'category-cont' => 0));
if ($allow_types['category-cat'] || $allow_types['category-cont']) {
if ($type != 'category-cat') {
$types_list = array();
if ($allow_types['category-cat']) {
$types_list['category-cat'] = t('Category');
}
if ($allow_types['category-cont']) {
$types_list['category-cont'] = t('Container');
}
$types_list['none'] = t('None');
$form['workflow']['category_nodeapi_'. $type] = array(
'#type' => 'radios',
'#title' => t('Category behavior'),
'#default_value' => variable_get('category_nodeapi_'. $type, 'none'),
'#options' => $types_list,
'#description' => t('Adds category or container behaviour to this content type. Setting this to a value other than \'none\' will add additional settings to any content of this type that you create or edit.')
);
}
if ($allow_types['category-cat']) {
$containers = array();
foreach (category_get_containers() as $key => $value) {
$containers[$key] = $value->admin_title;
}
$default_containers = variable_get('category_nodeapi_'. $type .'_containers', array(0 => 'all'));
$form['workflow']['category_nodeapi_'. $type .'_containers'] = array(
'#type' => 'select',
'#title' => t('Category - allowed containers'),
'#default_value' => $default_containers,
'#options' => (array('all' => '<'. t('All except') .'>') + $containers),
'#multiple' => TRUE,
'#description' => t('Applies only if this content type has its category behavior set to \'category\'. If so, this specifies the containers that are available for categories that are created or edited using this content type. Leave as default (\'all except\') to allow all containers. If you select the default value as well as other values, then all containers except the ones you have selected will be allowed.')
);
}
}
}
break;
// node edit form
case $type .'_node_form':
$cat_type = variable_get('category_nodeapi_'. $type, 'none');
if ($cat_type != 'none') {
$form += category_get_form(($cat_type == 'category-cat'), $node, FALSE);
}
$activeselect = module_exist('activeselect');
$cats = $node->category;
if (!isset($cats)) {
$cats = array();
}
$default_cat = NULL;
if (strpos($_GET['q'], 'node/add') !== FALSE && is_numeric(arg(3))) {
$default_cat = arg(3);
}
$c = db_query(db_rewrite_sql("SELECT cn.*, n.title FROM {category_cont} cn INNER JOIN {category_cont_node_types} cnt ON cn.cid = cnt.cid INNER JOIN {category} c ON cn.cid = c.cid INNER JOIN {node} n ON cn.cid = n.nid WHERE cnt.type = '%s' AND n.status = 1 AND n.moderate = 0 ORDER BY c.weight, n.title", 'cn', 'cid'), $node->type);
if (db_num_rows($c) > 0) {
$form['category'] = array(
'#type' => 'fieldset',
'#title' => t('Categories'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['category']['#tree'] = TRUE;
}
while ($container = db_fetch_object($c)) {
if ($container->tags) {
$typed_cats = array();
foreach ($cats as $cat) {
if ($cat->cnid == $container->cid) {
// Commas and quotes in terms are special cases, so encode 'em.
if (preg_match('/,/', $cat->title) || preg_match('/"/', $cat->title)) {
$cat->title = '"'.preg_replace('/"/', '""', $cat->title).'"';
}
$typed_cats[] = $cat->title;
}
}
$typed_string = implode(', ', $typed_cats) . (isset($cats['tags']) ? $cats['tags'][$container->cid] : NULL);
if ($container->help) {
$help = $container->help;
}
else {
$help = t('A comma-separated list of terms describing this content. Example: funny, bungie jumping, "Company, Inc.".');
}
$form['category']['tags'][$container->cid] = array(
'#type' => 'textfield',
'#default_value' => $typed_string,
'#maxlength' => 100,
'#autocomplete_path' => 'category/autocomplete/'. $container->cid,
'#required' => $container->required,
'#title' => $container->admin_title,
'#weight' => $container->weight,
'#description' => $help,
);
}
else {
$node_cats = array();
foreach ($cats as $cat) {
if ($cat->cnid == $container->cid) {
$node_cats[] = $cat->cid;
}
}
if (isset($default_cat)) {
$node_cats[] = $default_cat;
}
if (empty($node_cats)) {
$node_cats = NULL;
}
$form['category'][$container->cid] = category_form_node($container->cid, $node_cats, $container->help, 'category');
$form['category'][$container->cid]['#weight'] = $container->weight;
}
}
if ($activeselect && isset($form['category']) && is_array($form['category'])) {
foreach ($form['category'] as $cnid => $container) {
if ($cnid == 'tags' || !is_numeric($cnid)) {
continue;
}
$dist_containers = category_get_distant_child_containers($cnid);
$is_activeselect = FALSE;
$dist_cnids = array();
foreach ($dist_containers as $dist_cnid) {
if (isset($form['category'][$dist_cnid])) {
$dist_cnids[] = 'category-'. $dist_cnid;
}
}
if (!empty($dist_cnids)) {
$form['category'][$cnid]['#type'] = 'activeselect';
$activeselect_attrs = array(
'#activeselect_path' => 'category/activeselect',
'#activeselect_targets' => implode(',', $dist_cnids),
'#activeselect_extra' => ($node->nid ? $node->nid : 0). ($default_cat ? ','. $default_cat : ''),
);
$form['category'][$cnid] += $activeselect_attrs;
}
}
}
break;
}
}
/**
* Make sure incoming cnids are free tagging enabled.
*/
function category_node_validate(&$node) {
if ($node->category) {
$cats = $node->category;
if ($cats['tags']) {
foreach ($cats['tags'] as $cnid => $cnid_value) {
$container = category_get_container($cnid);
if (!$container->tags) {
form_set_error("category[tags][$cnid", t('The %name container can not be modified in this way.', array('%name' => theme('placeholder', $container->name))));
}
}
}
}
}
/**
* Menu callback; displays all nodes associated with a category.
*/
function category_category_page($str_cids = '', $depth = 0, $op = 'page') {
if (preg_match('/^([0-9]+[+ ])+[0-9]+$/', $str_cids)) {
$operator = 'or';
// The '+' character in a query string may be parsed as ' '.
$cids = preg_split('/[+ ]/', $str_cids);
}
else if (preg_match('/^([0-9]+,)*[0-9]+$/', $str_cids)) {
$operator = 'and';
$cids = explode(',', $str_cids);
}
else {
drupal_not_found();
}
// Needed for '+' to show up in RSS discovery URLs
$rss_cids = urlencode($str_cids);
if ($cids) {
$result = db_query(db_rewrite_sql('SELECT c.cid, n.title FROM {category} c INNER JOIN {node} n ON c.cid = n.nid WHERE c.cid IN (%s) AND n.status = 1 AND n.moderate = 0', 'n', 'nid'), implode(',', $cids));
$cids = array(); // we rebuild the $cids-array so it only contains categories the user has access to.
$names = array();
while ($cat = db_fetch_object($result)) {
$cids[] = $cat->cid;
$names[] = $cat->title;
}
if ($names) {
$title = check_plain(implode(', ', $names));
drupal_set_title($title);
switch ($op) {
case 'page':
drupal_add_link(array('rel' => 'alternate',
'type' => 'application/rss+xml',
'title' => 'RSS - '. $title,
'href' => url('category/'. $rss_cids .'/'. $depth .'/feed')));
$output = category_render_nodes(category_select_nodes($cids, $operator, $depth, TRUE, TRUE));
$output .= theme('feed_icon', url("category/$rss_cids/$depth/feed"));
return $output;
break;
case 'feed':
$cat = category_get_category($cids[0]);
$channel['link'] = url('category/'. $str_cids .'/'. $depth, NULL, NULL, TRUE);
$channel['title'] = variable_get('site_name', 'drupal') .' - '. $title;
$channel['description'] = $cat->description;
$result = category_select_nodes($cids, $operator, $depth, FALSE, TRUE);
node_feed($result, $channel);
break;
default:
drupal_not_found();
}
}
else {
drupal_not_found();
}
}
}
/**
* Menu callback; invokes the category export API.
*/
function category_export_page($type = 'html', $nid = 0) {
category_export($type, $nid);
}
/**
* Returns the content of a given node. If $teaser if true, returns
* the teaser rather than full content. Displays the most recently
* approved revision of a node (if any) unless we have to display this
* page in the context of the moderation queue.
*/
function category_content($node, $teaser = FALSE) {
// Extract the page body.
$node = node_prepare($node, $teaser);
return $node;
}
function category_category_path($category) {
$container = category_get_container($category->cnid);
if ($container->module != 'category' && $path = module_invoke($container->module, 'category_path', $category)) {
return $path;
}
return 'node/'. $category->cid;
}
/**
* Provides category information for rss feeds
*/
function category_rss_item($node) {
$output = array();
foreach ($node->category as $cat) {
$is_included = TRUE;
if (module_exist('category_display')) {
$cont = category_display_cont_load($cat->cnid);
if (!$cont->nodelinks) {
$is_included = FALSE;
}
}
if ($is_included) {
$output[] = array('key' => 'category',
'value' => check_plain($cat->title),
'attributes' => array('domain' => url('node/'. $cat->cid, NULL, NULL, TRUE)));
}
}
return $output;
}
/**
* Helper function for autocompletion
*/
function category_autocomplete($cnid, $string = '') {
// The user enters a comma-separated list of tags. We only autocomplete the last tag.
// This regexp allows the following types of user input:
// this, "somecmpany, llc", "and ""this"" w,o.rks", foo bar
$regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
preg_match_all($regexp, $string, $matches);
$array = $matches[1];
// Fetch last tag
$last_string = trim(array_pop($array));
if ($last_string != '') {
$result = db_query_range(db_rewrite_sql("SELECT n.title FROM {category} c INNER JOIN {node} n ON c.cid = n.nid WHERE c.cnid = %d AND LOWER(n.title) LIKE LOWER('%%%s%%') AND n.status = 1 AND n.moderate = 0"), $cnid, $last_string, 0, 10);
$prefix = count($array) ? implode(', ', $array) .', ' : '';
$matches = array();
while ($tag = db_fetch_object($result)) {
$n = $tag->title;
// Commas and quotes in terms are special cases, so encode 'em.
if (preg_match('/,/', $tag->title) || preg_match('/"/', $tag->title)) {
$n = '"'. preg_replace('/"/', '""', $tag->title) .'"';
}
$matches[$prefix . $n] = check_plain($tag->title);
}
print drupal_to_js($matches);
exit();
}
}
/**
* Helper function for activeselect form elements
*/
function category_activeselect($source, $targets, $string = NULL, $extra = NULL) {
if (empty($targets) || empty($source) || empty($string) || !isset($extra)) {
exit();
}
$nid = NULL;
$parent_cont = NULL;
if (strpos($extra, ',') === FALSE) {
$nid = $extra;
}
else {
$extra_array = explode(',', $extra);
$nid = $extra_array[0];
$parent_cont = $extra_array[1];
}
$array = activeselect_explode_values($string);
$targets = explode(',', $targets);
if (count($targets) == 1 && $targets[0] == 'parents') {
foreach ($array as $cnid => $value) {
$parents = array();
$exclude = array();
if (!empty($nid) && is_numeric($nid)) {
$node = node_load($nid);
$parents = array_keys(category_get_parents($node->nid));
$children = category_get_tree($node->cnid, $node->nid, -1, 2, TRUE); # deavid, modificado: Depth era NULL.
foreach ($children as $child) {
$exclude[] = $child->cid;
}
$exclude[] = $node->nid;
}
$cont = category_get_container($cnid);
$multiple = ($cont->hierarchy == 2);
if ($parent_cont) {
$parents = array($parent_cont);
}
$options = _category_category_select_options($cnid, $multiple, '<'. t('root') .'>', $parents, $exclude);
foreach ($options as $key => $value) {
unset($options[$key]);
$options[$key]['value'] = $value;
$options[$key]['selected'] = in_array($key, $parents);
}
$output = array($targets[0] => array('options' => $options, 'multiple' => $multiple));
activeselect_set_header_nocache();
print drupal_to_js($output);
exit();
}
}
elseif (preg_match('/^category-\d+$/', $targets[0])) {
$output = array();
foreach ($targets as $target) {
$options = array();
$split = explode('-', $target);
$cnid = $split[1];
$container = category_get_container($cnid);
$node = node_load($nid);
$split = explode('-', $source);
$parent_cnid = $split[1];
if ($container->required) {
$blank = 0;
}
else {
$blank = '<'. t('none') .'>';
}
$node_cats = array();
if ($nid) {
$cats = $node->category;
if (isset($cats)) {
if (is_array($cats)) {
foreach ($cats as $cat) {
if ($cat->cnid == $cnid) {
$node_cats[] = $cat->cid;
}
}
}
elseif (!empty($cats)) {
$node_cats[] = $cats;
}
}
}
if (isset($parent_cont)) {
$node_cats[] = $parent_cont;
}
if (empty($node_cats)) {
$node_cats = NULL;
}
$options = _category_node_select_options($cnid, $blank, $node_cats);
if (isset($options) && is_array($options)) {
foreach ($options as $key => $value) {
$parents_in_cont = FALSE;
$matching_parents = FALSE;
$parents = category_get_parents($key);
foreach ($parents as $cid => $x) {
$parent_cat = category_get_category($cid);
if ($parent_cat->cnid == $parent_cnid) {
$parents_in_cont = TRUE;
if (isset($array[$cid])) {
$matching_parents = TRUE;
}
}
}
if ($parents_in_cont && !$matching_parents) {
unset($options[$key]);
}
}
foreach ($options as $key => $value) {
unset($options[$key]);
$options[$key]['value'] = $value;
$options[$key]['selected'] = in_array($key, $parents);
$options[$key] = str_replace('|', '|', $options[$key]);
if (is_array($node_cats)) {
$options[$key]['selected'] = in_array($key, $node_cats);
}
else {
$options[$key]['selected'] = ($key == $node_cats);
}
}
}
$multiple = ($container->multiple ? TRUE : FALSE);
$output[$target] = array('options' => $options, 'multiple' => $multiple);
}
activeselect_set_header_nocache();
print drupal_to_js($output);
}
exit();
}
/**
* The category wrapper install / uninstall script.
*
* @param $type
* The wrapper being installed or uninstalled ('taxonomy' or 'book').
* @param $op
* The operation being performed ('install' or 'uninstall').
*/
function category_wrapper($type = NULL, $op = NULL) {
$goto = 'admin/settings/category';
$generic_error = ' '. t('Unable to perform the specified operation.');
// Various validation checks
if (!($type == 'taxonomy' || $type == 'book') || !($op == 'install' || $op == 'uninstall')) {
drupal_set_message(t('Invalid parameters supplied to wrapper install / uninstall script.'). $generic_error, 'error');
drupal_goto($goto);
}
if (!module_exist($type)) {
drupal_set_message(t('The %type module is not currently enabled. You must enable it before performing an install or uninstall.', array('%type' => $type)), 'error');
drupal_goto($goto);
}
$status = category_get_wrapper_status($type);
if (($status && $op == 'install') || (!$status && $op == 'uninstall')) {
drupal_set_message(t('The %type module is already %status.', array('%type' => $type, '%status' => ($status ? t('installed') : t('uninstalled')))). $generic_error, 'error');
drupal_goto($goto);
}
$module_path = drupal_get_path('module', $type);
$module_file = $type. '.module';
$module_file_path = $module_path. '/'. $module_file;
if (!file_exists($module_file_path)) {
drupal_set_message(t('The file %filename could not be found.', array('%filename' => $module_file)). $generic_error, 'error');
drupal_goto($goto);
}
if ($op == 'install') {
$wrapper_file = $type. '.module.copyme';
$wrapper_file_path = drupal_get_path('module', 'category'). '/wrappers/'. $wrapper_file;
if (!file_exists($wrapper_file_path)) {
drupal_set_message(t('The file %filename could not be found.', array('%filename' => $wrapper_file)). $generic_error, 'error');
drupal_goto($goto);
}
if (!@copy($wrapper_file_path, $module_path. '/'. $wrapper_file)) {
drupal_set_message(t('The file %filename could not be copied.', array('%filename' => $wrapper_file)). $generic_error, 'error');
drupal_goto($goto);
}
if (!@rename($module_file_path, $module_file_path. '.old')) {
drupal_set_message(t('The file %filename could not be renamed.', array('%filename' => $module_file)). $generic_error, 'error');
drupal_goto($goto);
}
$wrapper_new_path = $module_path. '/'. $wrapper_file;
if (!@rename($wrapper_new_path, $module_file_path)) {
drupal_set_message(t('The file %filename could not be renamed.', array('%filename' => $wrapper_file)). $generic_error, 'error');
drupal_goto($goto);
}
}
else {
$old_file = $type. '.module.old';
$old_file_path = drupal_get_path('module', $type). '/'. $old_file;
if (!file_exists($old_file_path)) {
drupal_set_message(t('The file %filename could not be found.', array('%filename' => $old_file)). $generic_error, 'error');
drupal_goto($goto);
}
if (!@unlink($module_file_path)) {
drupal_set_message(t('The file %filename could not be deleted.', array('%filename' => $module_file)). $generic_error, 'error');
drupal_goto($goto);
}
if (!@rename($old_file_path, $module_file_path)) {
drupal_set_message(t('The file %filename could not be renamed.', array('%filename' => $old_file)). $generic_error, 'error');
drupal_goto($goto);
}
}
drupal_set_message(t('The %type wrapper was %op successfully.', array('%type' => $type, '%op' => ($op == 'install' ? t('installed') : t('uninstalled')))));
module_list(TRUE, FALSE);
menu_rebuild();
drupal_goto($goto);
}
function theme_category_view($node) {
$nodes = category_select_nodes(array($node->nid), 'or', $node->depth, TRUE, TRUE);
$type = category_node_get_type($node);
$show_nodes = FALSE;
if (db_num_rows($nodes) > 0) {
if (!module_exist('category_display') || $node->show_listing) {
$show_nodes = TRUE;
}
}
else {
if (!module_exist('category_display')) {
if ($type == 'category-cont') {
if ($node->depth) {
$show_nodes = TRUE;
}
}
else {
$show_nodes = TRUE;
}
}
else {
if ($node->show_listing) {
if ($type == 'category-cont') {
if ($node->depth && $node->emptymsg) {
$show_nodes = TRUE;
}
}
else {
if ($node->emptymsg) {
$show_nodes = TRUE;
}
}
}
}
}
// Allow other modules to add additional output.
$extra = module_invoke_all('category', 'view', $node);
if (isset($extra) && is_array($extra)) {
foreach ($extra as $key => $value) {
$node->body .= $value;
}
}
if ($show_nodes) {
drupal_add_link(array('rel' => 'alternate',
'type' => 'application/rss+xml',
'title' => 'RSS - '. $node->title,
'href' => url('node/'. $node->nid .'/feed')));
$use_views = FALSE;
if (module_exist('category_views')) {
$use_views = category_views_is_visible($node, $type);
}
if ($use_views) {
$node->body .= category_views_render_nodes($node);
}
else {
$node->body .= category_render_nodes($nodes);
}
$node->body .= theme('feed_icon', url("node/$node->nid/feed"));
}
return $node->body;
}
/**
* The interface for the category wrapper install / uninstall script.
*
* @param $type
* The type of wrapper interface being themed ('taxonomy' or 'book').
* @param $status
* Boolean indicating if the specified wrapper is currently installed.
*
* @return
* Themed output.
*/
function theme_category_wrapper_status($type, $status) {
theme_add_style(drupal_get_path('module', 'category'). '/category.css');
$output = '';
if (module_exist($type)) {
$status_string = $status ? (''. t('installed'). '') : (''. t('not installed'). '');
$output .= ''. t('The %type wrapper is currently %status-string.', array('%type' => $type, '%status-string' => $status_string)). "\n";
$install_string = $status ? t('Uninstall now') : t('Install now');
$op = $status ? 'uninstall' : 'install';
$output .= '
'. (l($install_string, t('category/wrapper/%type/%op', array('%type' => $type, '%op' => $op)))). ".
\n";
}
else {
$status_string = ''. t('not enabled'). '';
$output .= ''. t('The %type module (original or wrapper) is currently %status-string. You must enable it on the %module-admin-page before you can perform an install or an uninstall.', array('%type' => $type, '%status-string' => $status_string, '%module-admin-page' => l(t('module administration page'), 'admin/modules'))). "
\n";
}
return $output;
}
/**
* Makes it easier to assign these common combinations of permissions.
* Think of this as a shorthand function for category access control.
*/
function _category_privileged($type = 'create all') {
switch ($type) {
case 'create categories':
return user_access('create categories') || user_access('administer categories');
case 'create containers':
return user_access('create containers') || user_access('administer categories');
case 'edit all':
return user_access('edit all categories') || user_access('administer categories');
case 'create all':
return user_access('create categories') || user_access('create containers') || user_access('administer categories');
default:
return FALSE;
}
}
/**
* Returns an array containing all the fields of the container table.
*/
function _category_get_container_fields() {
return array('cid', 'admin_title', 'help', 'module', 'has_relations', 'has_synonyms', 'hierarchy', 'multiple', 'required', 'tags', 'hidden_cont');
}
function _category_container_insert($node, $stage, $fields = NULL) {
if (!isset($fields) || !is_array($fields)) {
$fields = _category_get_container_fields();
}
if ($stage == 1) {
$result = implode(', ', $fields);
}
else {
foreach ($fields as $key) {
$value = $node->$key;
if (isset($value)) {
//Escape strings, but not integers
if (is_numeric($value)) {
$q[] = $value;
}
elseif (is_array($value)) {
$q[] = "'". implode(',', $value) ."'";
}
else {
$q[] = "'". str_replace('%', '%%', db_escape_string($value)) ."'";
}
}
else {
$q[] = 0;
}
}
$result = implode(', ', $q);
}
return "($result)";
}
function _category_container_update($node, $fields = NULL) {
if (!isset($fields) || !is_array($fields)) {
$fields = _category_get_container_fields();
}
foreach ($fields as $key) {
$value = $node->$key;
if (isset($value)) {
if (is_array($value)) {
$q[] = "$key = '". implode(',', $value) ."'";
}
else {
$q[] = "$key = '". str_replace('%', '%%', db_escape_string($value)) ."'";
}
}
}
$result = implode(', ', $q);
return $result;
}
/**
* Generates a select element for choosing parents.
*
* @return
* The select form element as an array.
*/
function _category_category_select($title, $value, $cnid, $description, $multiple, $blank, $exclude = array()) {
$options = _category_category_select_options($cnid, $multiple, $blank, $value, $exclude);
return array(
'#type' => 'select',
'#title' => $title,
'#default_value' => $value,
'#options' => $options,
'#description' => $description,
'#multiple' => $multiple,
'#size' => $multiple ? min(12, count($options)) : 0,
'#required' => TRUE,
);
}
/**
* Helper function for _category_category_select(). Retrieves the options with
* which to fill the select list for the parent selection box.
*
* @return
* An array of options for use in a select list.
*/
function _category_category_select_options($cnid, $multiple, $blank, &$value, $exclude = array()) {
$options = array();
$container = NULL;
if ($cnid) {
$category = category_get_category($cnid);
if ($category->cnid) {
$container = category_get_container($category->cnid);
}
else {
$container = category_get_container($cnid);
}
}
//var_dump($container);
$tree = category_get_tree($container->parent,0, -1 , 2); # deavid, modificado. Depth era NULL
if ($blank && (!$container || in_array('root', $container->children_allowed_parents))) {
$options[0] = $blank;
}
if (!empty($tree)) {
$default_set = FALSE;
foreach ($tree as $category) {
// Boolean blasphemy has been cleaned up and moved to separate function
if (_category_category_select_check_category($category, $container, $cnid, $exclude)) {
$options[$category->cid] = _category_depth($category->depth, '-') . ($category->cnid ? $category->title : $category->admin_title) . ($category->cnid ? '' : ' *');
}
}
if (!$blank && !$value && !$multiple && !$default_set) {
// required but without a predefined value, so set first as predefined
$value = key($trees) ? key($trees) : $tree[0]->cid;
$default_set = TRUE;
}
}
return $options;
}
/**
* Helper function for _category_category_select(). Determines if a particular
* category should be included in the select list.
*
* @param $category
* The category or container to be checked for inclusion.
* @param $container
* The container that $category is in, or if $category is a container, its
* extra container information.
* @param $cnid
* The node ID of the container for which a select list is being generated.
* @param $exclude
* An array of categories to be explicitly excluded from the select list.
*
* @return
* Boolean TRUE if the category is to be included, FALSE otherwise,
*/
function _category_category_select_check_category($category, $container, $cnid, $exclude) {
// Categories in the $exclude array are easy to knock off first.
if (in_array($category->cid, $exclude)) {
return FALSE;
}
// Next, we get rid of categories that the user does not have access to
if (!node_access('view', node_load($category->cid))) {
return FALSE;
}
// If no container has been specified, then all categories from all
// containers should be returned.
if (!isset($container)) {
return TRUE;
}
$this_cat_cont = category_get_container($category->cnid);
// We have a category
if ($category->cnid) {
// Only list possible parents if its container supports parents
if ($this_cat_cont->hierarchy) {
// The category is in one of the allowed containers
if (in_array($category->cnid, $container->children_allowed_parents)) {
return TRUE;
}
// The category is in this container
elseif (!$container->children_have_distant && $category->cnid == $cnid) {
return TRUE;
}
}
}
// We have a container
else {
// The container is one of the allowed ones
if (in_array($category->cid. '#', $container->children_allowed_parents)) {
return TRUE;
}
// The container is this container
elseif (!$container->children_have_distant && $category->cid == $cnid) {
return TRUE;
}
}
return FALSE;
}
function _category_node_select($title, $value, $cnid, $description, $multiple, $blank, $exclude = array()) {
$options = _category_node_select_options($cnid, $blank, $value, $exclude);
return array(
'#type' => 'select',
'#title' => $title,
'#default_value' => $value,
'#options' => $options,
'#description' => $description,
'#multiple' => $multiple,
'#size' => $multiple ? min(12, count($options)) : 0,
'#required' => TRUE,
);
}
function _category_node_select_options($cnid, $blank, &$value, $exclude = array()) {
$tree = category_get_tree($cnid, NULL, -1, 2); # deavid, depth era NULL
$options = array();
if ($blank) {
$options[0] = $blank;
}
if ($tree) {
foreach ($tree as $category) {
if (!in_array($category->cid, $exclude) && node_access('view', node_load($category->cid))) {
$options[$category->cid] = _category_depth($category->depth, '-') . $category->title;
}
}
if (!$blank && !$value) {
// required but without a predefined value, so set first as predefined
$value = $tree[0]->cid;
}
elseif ($blank && !$value) {
$value = 0;
}
}
return $options;
}
/**
* Determines whether or not a container is available for categories of a
* specified node type.
*
* @param $type
* The node type of the category.
* @param $cnid
* The node ID of the container.
*
* @return
* Boolean indicating whether or not the container is available for the
* specified node type.
*/
function _category_type_allowed_container($type, $cnid) {
$cont_list = variable_get('category_nodeapi_'. $type .'_containers', array(0 => 'all'));
if (empty($cont_list) || !is_array($cont_list)) {
return TRUE;
}
// Convert the array into key-value pairs where the keys are the same as
// the values.
$containers = array();
foreach ($cont_list as $key => $value) {
$containers[$value] = $value;
}
// Use a separate variable to track the 'all except' flag.
$all_except = isset($containers['all']);
unset($containers['all']);
// The container is allowed if it is selected, and the 'all except' flag is
// not set. If the 'all except' flag is set, and the container is selected,
// then it is not allowed.
if (isset($containers[$cnid])) {
return !$all_except;
}
// If the container is not selected, and the 'all except' flag is set, the
// container is allowed. If the 'all except' flag is set, and the container
// is selected, it is not allowed. If no containers are selected, and 'all
// except' is selected, it is allowed.
return $all_except;
}