aggregator2-4.6.x-1.x-dev/aggregator2_autotaxonomy.module
aggregator2_autotaxonomy.module
<?php
/*
* Aggregator2 Autotaxonomy
*
* @file
* Allows Aggregator2 RSS items with <category> tags to auto create Drupal taxonomy terms.
* @author Budda <mike@buddasworld.co.uk>
* @author Marcin Konicki <ahwayakchih@gmail.com>
*/
/**
* Implementation of hook_help().
*/
function aggregator2_autotaxonomy_help($section) {
switch ($section) {
case 'admin/modules#description':
return t('Creates & assign taxonomy terms to RSS feed items from <category> tags.');
case 'admin/settings/aggregator2_autotaxonomy':
return '<p>' . t('If the %url include %category tag information
to organise the items, then this module will automatically create the same category in the
%taxurl so that you can organise your aggregated posts.', array('%taxurl' => l('taxonomy system', 'admin/taxonomy'), '%url' => l('RSS feeds you are aggregating', 'admin/aggregator2'), '%category' => theme('placeholder', '<category>')) ) . '</p>';
}
}
function aggregator2_autotaxonomy_perm() {
return array('add new categories');
}
function aggregator2_autotaxonomy_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
switch ($op) {
case 'load':
// remember title, for case when it's changed and we will want to change category name
$node->agg2_old_title = $node->title;
break;
case 'form post':
{
$vid = variable_get('agg2_autotaxonomy_easy_vid', 0);
if ($vid > 0 && user_access('add new categories')) {
$vocab = taxonomy_get_vocabulary($vid);
if (in_array($node->type, $vocab->nodes)) {
$temp = '';
$temp .= form_textfield(t('New categories'), 'agg2_autotaxonomy_add_cat', $edit['agg2_autotaxonomy_add_cat'], 50, 128, t('List of comma separated categories. Example: "Linux,Windows,Operating systems".'), NULL, FALSE);
if ($node->type == 'aggregator2-feed') {
$temp .= form_checkbox(t('Apply also to items'), 'agg2_autotaxonomy_items_too', 1, $edit['agg2_autotaxonomy_items_too'], t('If enabled, list of categories above will also be used for aggregated items.'));
}
return form_group(t('Additional categories'), $temp);
}
}
break;
}
case 'form pre':
if ($node->type == 'aggregator2-feed') {
return form_hidden('agg2_old_title', $node->title);
}
break;
case 'insert':
if (isset($node->agg2_autotaxonomy_add_cat) && trim($node->agg2_autotaxonomy_add_cat) != '' && user_access('add new categories')) {
// remember old taxonomy, so we can compare with updated and apply new terms to items
$old = $node->taxonomy;
$terms = explode(',', $node->agg2_autotaxonomy_add_cat);
_aggregator2_autotaxonomy_aggregate($node, $terms, variable_get('agg2_autotaxonomy_easy_vid', 0));
if ($node->agg2_autotaxonomy_items_too) {
$terms = array_diff($node->taxonomy, $old); // find new
$node->feed_item_taxonomy = array_merge($node->feed_item_taxonomy, $terms); // add them
// save
db_query('UPDATE {aggregator2_feed} SET item_taxonomy = \'%s\' WHERE nid = %d', serialize($node->feed_item_taxonomy), $node->nid);
}
}
if ($node->type == 'aggregator2-feed') {
_aggregator2_autotaxonomy_add($node);
}
else if ($node->type == 'aggregator2-item') {
_aggregator2_autotaxonomy_aggregate($node);
}
break;
case 'update':
if (isset($node->agg2_autotaxonomy_add_cat) && trim($node->agg2_autotaxonomy_add_cat) != '' && user_access('add new categories')) {
// remember old taxonomy, so we can compare with updated and apply new terms to items
$old = $node->taxonomy;
$terms = explode(',', $node->agg2_autotaxonomy_add_cat);
_aggregator2_autotaxonomy_aggregate($node, $terms, variable_get('agg2_autotaxonomy_easy_vid', 0));
if ($node->agg2_autotaxonomy_items_too) {
$terms = array_diff($node->taxonomy, $old); // find new
$node->feed_item_taxonomy = array_merge($node->feed_item_taxonomy, $terms); // add them
// save
db_query('UPDATE {aggregator2_feed} SET item_taxonomy = \'%s\' WHERE nid = %d', serialize($node->feed_item_taxonomy), $node->nid);
}
}
if ($node->type == 'aggregator2-feed') {
_aggregator2_autotaxonomy_update($node);
}
else if ($node->type == 'aggregator2-item') {
_aggregator2_autotaxonomy_aggregate($node);
}
break;
case 'delete':
if ($node->type == 'aggregator2-feed') {
_aggregator2_autotaxonomy_delete($node);
}
break;
}
}
function aggregator2_autotaxonomy_settings() {
$output = '';
$vocabs = db_query("SELECT v.vid, v.name FROM {vocabulary} v INNER JOIN {vocabulary_node_types} n ON v.vid = n.vid WHERE n.type = '%s' ORDER BY v.weight, v.name", 'aggregator2-item');
// Build list of available vocabularies
$options = array();
$options[0] = '-------';
while ($vocabulary = db_fetch_object($vocabs)) {
$options[$vocabulary->vid] = $vocabulary->name;
}
if(count($options) > 1) {
$temp = form_select(t('Vocabulary'), 'aggregator2_autotaxonomy_vocabulary', variable_get('aggregator2_autotaxonomy_vocabulary', 0), $options, t('Which vocabulary should the auto created category names be associated with? Select dashed line to disable this feature.'), 0, FALSE, FALSE);
}
else {
$temp = '<p>' . t("You need to associate a %url with the node type %node to use this module.
If you don't have any vocabularies set-up you can %addurl now.",
array('%url' => l('vocabulary', 'admin/taxonomy'),
'%node' => theme('placeholder', 'aggregator2 news feed item'),
'%addurl' => l('add one', 'admin/taxonomy/add/vocabulary')
)) . '</p>';
}
$output .= form_group(t('Aggregation of categories'), $temp);
if(count($options) > 1) {
$temp = form_select(t('Vocabulary'), 'agg2_autotaxonomy_feed_vid', variable_get('agg2_autotaxonomy_feed_vid', 0), $options, t('Which vocabulary should the auto created category names be associated with? Select dashed line to disable this feature.'), 0, FALSE, FALSE);
$temp .= form_checkbox(t('Apply to feed items also'), 'agg2_autotaxonomy_items_too', 1, variable_get('agg2_autotaxonomy_items_too', 0), t('If enabled, auto created term will be used also for future feed\'s items'));
$output .= form_group(t('Autocreation of feed\'s categories'), $temp, t('Select vocabulary above if you want autotaxonomy module to automatically create term for each new feed. Such term will get name of the feed.'));
}
if(count($options) > 1) {
$temp = form_select(t('Vocabulary'), 'agg2_autotaxonomy_easy_vid', variable_get('agg2_autotaxonomy_easy_vid', 0), $options, t('Which vocabulary should the "easy created" category names be associated with? Select dashed line to disable this feature.'), 0, FALSE, FALSE);
$output .= form_group(t('Easy categories'), $temp, t('Select vocabulary above if you want autotaxonomy module to allow to specify set of terms by just writing them in input field. Such terms will be added to vocabulary specified above and will be associated with node being edited.'));
}
return $output;
}
function _aggregator2_autotaxonomy_aggregate(&$node, $categories = array(), $vocab = 0) {
static $cat_names;
if (!is_array($cat_names)) {
$cat_names = array();
}
if ($vocab == 0) {
$vocab = variable_get('aggregator2_autotaxonomy_vocabulary', 0);
}
if ($vocab == 0) {
//watchdog('aggregator2', t('No vocabulary has been set for autotaxonomy to use.'), WATCHDOG_WARNING, l('set', 'admin/settings/aggregator2_autotaxonomy'));
return;
}
if (count($categories) < 1 && isset($node->rss_item_data)) {
//[RSS:CATEGORY][][VALUE] && [RSS:CATEGORY][][DOMAIN] attrib
//[ATOM:CATEGORY][][TERM][][VALUE]
//[DC:SUBJECT][][VALUE]
if ($node->rss_item_data['CATEGORY'][0]['VALUE']) $categories = $node->rss_item_data['CATEGORY']; // RSS 0.92, 2.0
else if ($node->rss_item_data['CATEGORY'][0]['TERM'][0]['VALUE']) $categories = $node->rss_item_data['CATEGORY']; // ATOM 1.0
else if ($node->rss_item_data['ATOM:CATEGORY'][0]['TERM'][0]['VALUE']) $categories = $node->rss_item_data['ATOM:CATEGORY']; // ATOM 1.0
else if ($node->rss_item_data['SUBJECT']) $categories = $node->rss_item_data['SUBJECT']; // DublinCore
else if ($node->rss_item_data['DC:SUBJECT']) $categories = $node->rss_item_data['DC:SUBJECT']; // DublinCore
}
// If the RSS item has any category tags, add new ones to taxonomy if needed
if (count($categories) > 0) {
if (!isset($node->taxonomy) || !is_array($node->taxonomy)) {
$node->taxonomy = array();
}
foreach ($categories as $category_name) {
if (is_array($category_name)) {
if ($category_name['TERM']) { // ATOM 1.0
$category_name = strtolower($category_name['TERM'][0]['VALUE']);
}
else { // RSS 0.92, RSS 2.0, DublinCore
$category_name = strtolower($category_name['VALUE']);
}
}
else {
$category_name = strtolower($category_name);
}
if (trim($category_name) != '') {
if (!isset($cat_names[$category_name])) {
$temp = module_invoke('taxonomy', 'get_term_by_name', $category_name);
foreach ($temp as $cat) {
if ($cat->vid == $vocab) {
$cat_names[$category_name] = $cat->tid;
}
}
}
// Create a new category term
if (!isset($cat_names[$category_name])) {
$term = array();
$term['name'] = $category_name;
$term['description'] = t('Auto generated by aggregator2 autotaxonomy');
$term['vid'] = $vocab;
$term['weight'] = 0;
$term = taxonomy_save_term($term);
$node->taxonomy[] = $term['tid'];
$cat_names[$category_name] = $term['tid'];
}
else {
// Use the existing category term in the database
if (!in_array($cat_names[$category_name], $node->taxonomy)) {
$node->taxonomy[] = $cat_names[$category_name];
}
}
}
}
}
}
function _aggregator2_autotaxonomy_add(&$node) {
$category_name = strtolower($node->title);
$vocab = variable_get('agg2_autotaxonomy_feed_vid', 0);
if (trim($category_name) == '' || $vocab == 0) {
return NULL;
}
$cat = module_invoke('taxonomy', 'get_term_by_name', $category_name);
$term = NULL;
foreach ($cat as $t) {
if ($t->vid == $vocab) {
$term = object2array($t);
break;
}
}
// Make sure node has only one term from that vocab (so in case of being created from template it doesn't keep template's term)
if (is_array($node->taxonomy)) {
$old = db_query('SELECT tid FROM {term_data} WHERE tid IN (%s) AND vid = %d', implode(',', $node->taxonomy), $vocab);
$rm = array();
while ($temp = db_fetch_object($old)) {
$rm[] = $temp->tid;
}
$node->taxonomy = array_diff($node->taxonomy, $rm);
if (is_array($node->feed_item_taxonomy)) {
$node->feed_item_taxonomy = array_diff($node->feed_item_taxonomy, $rm);
}
}
else {
$node->taxonomy = array();
}
// Create a new category term
if (!is_array($term)) {
$term['name'] = $category_name;
$term['description'] = '';
$term['vid'] = $vocab;
$term['weight'] = 0;
$term = taxonomy_save_term($term);
}
if ($term['vid'] == $vocab) {
$node->taxonomy[] = $term['tid'];
if (!is_array($node->feed_item_taxonomy)) {
$node->feed_item_taxonomy = array();
}
if (variable_get('agg2_autotaxonomy_items_too', 0) && !in_array($term['tid'], $node->feed_item_taxonomy)) {
$node->feed_item_taxonomy[] = $term['tid'];
// Aggregator2 goes before this one, so we have to modify database directly
db_query('UPDATE {aggregator2_feed} SET item_taxonomy = \'%s\' WHERE nid = %d', serialize($node->feed_item_taxonomy), $node->nid);
}
return $term['tid'];
}
}
function _aggregator2_autotaxonomy_update(&$node) {
$category_name = strtolower($node->title);
$vocab = variable_get('agg2_autotaxonomy_feed_vid', 0);
if (trim($category_name) == '' || $vocab == 0) {
return NULL;
}
$cat = module_invoke('taxonomy', 'get_term_by_name', $category_name);
$term = NULL;
foreach ($cat as $t) {
if ($t->vid == $vocab) {
$term = object2array($t);
break;
}
}
if (!is_array($term) && isset($node->agg2_old_title)) {
// try to find category by previous title of node (in case title was changed)
$cat = module_invoke('taxonomy', 'get_term_by_name', strtolower($node->agg2_old_title));
foreach ($cat as $t) {
if ($t->vid == $vocab) {
$term = object2array($t);
break;
}
}
}
if (is_array($term)) {
// update category name
$term['name'] = $category_name;
$term = taxonomy_save_term($term);
if (!in_array($term['tid'], $node->taxonomy)) {
$node->taxonomy[] = $term['tid'];
}
return $term['tid'];
}
else {
// just create new
return _aggregator2_autotaxonomy_add($node);
}
}
function _aggregator2_autotaxonomy_delete(&$node) {
$category_name = strtolower($node->title);
$vocab = variable_get('agg2_autotaxonomy_feed_vid', 0);
if (trim($category_name) == '' || $vocab == 0) {
return;
}
$cat = module_invoke('taxonomy', 'get_term_by_name', $category_name);
$term = NULL;
foreach ($cat as $t) {
if ($t->vid == $vocab) {
$term = $t;
}
}
if ($term == NULL || $term->vid != $vocab) {
return;
}
// Now check if there are still nodes with this category associated.
$result = db_query('SELECT * FROM {term_node} WHERE tid = %d LIMIT 1', $term->tid);
if ($result && $temp = db_fetch_object($temp)) {
return;
}
// Delete category only when there is no node associated with it
taxonomy_del_term($term->tid);
}
