'Calais Node Settings', 'description' => 'Configurations for Calais Integration with content nodes', 'page callback' => 'drupal_get_form', 'page arguments' => array('calais_admin_settings'), 'access arguments' => array('administer calais'), 'type' => MENU_LOCAL_TASK ); $items['node/%node/calais'] = array( 'title' => 'Calais', 'page callback' => 'drupal_get_form', 'page arguments' => array('calais_keywords_form', 1), 'access callback' => 'calais_access', 'access arguments' => array(1), 'weight' => 2, 'type' => MENU_LOCAL_TASK ); return $items; } /** * Implementation of hook_access() */ function calais_access($node) { return user_access('access calais') && calais_processing_type($node) != CALAIS_PROCESS_NO; } /** * Build the administration page for Calais and Content Types */ function calais_admin_settings() { $form = array(); calais_build_entity_settings($form); calais_build_nodetype_settings($form); $form['#submit'][] = 'calais_admin_settings_submit'; $form = system_settings_form($form); return $form; } /** * Build the Entity selector. Used for Entity suppression. */ function calais_build_entity_settings(&$form, $type = 'global', $name = 'Global', $allow_disable = false) { $entity_attributes = array(); $entities = array_keys(calais_get_entity_vocabularies()); sort($entities); $disabled = false; if ($allow_disable) { $var_name = "calais_use_global_{$type}"; $disabled = variable_get($var_name, true); $form[$var_name] = array( '#type' => 'checkbox', '#title' => t('Use Calais Global Entity defaults'), '#default_value' => $disabled, '#description' => t('If checked, this content type will use the Global Calais Entities.'), ); if ($disabled) { $entity_attributes['style'] = 'display:none'; } $field_id = 'edit-' . str_replace(array('][', '_', ' '), '-', $var_name); drupal_add_js("$(document).ready(function() { $('#$field_id').click(function() { $('.{$type}_entities').toggle(); }); });", 'inline'); } $params = array('@name' => $name); $form["calais_entity_settings_{$type}"] = array( '#type' => 'fieldset', '#title' => t('@name Calais Entities', $params), '#attributes' => array_merge(array('class' => "{$type}_entities"), $entity_attributes), '#collapsible' => TRUE, '#collapsed' => TRUE, ); $form["calais_entity_settings_{$type}"]["calais_applied_entities_{$type}"] = array( '#type' => 'checkboxes', '#title' => t('Which Calais Entities do you wish to use?'), '#default_value' => variable_get("calais_applied_entities_{$type}", $entities), '#options' => drupal_map_assoc($entities), '#description' => t('These are the entities that will get applied to content. If an Entity is not selected then the Calais suggestions will be ignored'), ); } /** * Build the node type settings form for Calais integration. */ function calais_build_nodetype_settings(&$form) { node_types_rebuild(); $node_types = node_get_types('types', NULL, TRUE); $options = array( CALAIS_PROCESS_NO => t('Not processed by Calais (default)'), CALAIS_PROCESS_MANUAL => t('Have keywords be suggested (manual term association)'), CALAIS_PROCESS_AUTO => t('Have keywords automatically applied'), ); foreach ($node_types as $nt) { $key = strtolower($nt->type); $name = $nt->name; $paramName = array('@node' => $name); $form["calais_{$key}_settings"] = array( '#type' => 'fieldset', '#title' => t('Processing Settings for @node', $paramName), '#collapsible' => TRUE, '#collapsed' => FALSE, ); $form["calais_{$key}_settings"]["calais_node_{$key}_process"] = array( '#type' => 'radios', '#parents' => array('calais_node_'. $key .'_process'), '#title' => t('Calais Processing'), '#default_value' => variable_get("calais_node_{$key}_process", CALAIS_PROCESS_NO), '#options' => $options, ); $form["calais_{$key}_settings"]["calais_api_allow_searching_{$key}"] = array( '#type' => 'checkbox', '#title' => t('Allow Calais Searching'), '#default_value' => variable_get("calais_api_allow_searching_{$key}", NULL), '#description' => t('Indicates whether future searches can be performed on the extracted metadata by Calais'), ); $form["calais_{$key}_settings"]["calais_api_allow_distribution_{$key}"] = array( '#type' => 'checkbox', '#title' => t('Allow Calais Distribution'), '#default_value' => variable_get("calais_api_allow_distribution_{$key}", NULL), '#description' => t('Indicates whether the extracted metadata can be distributed by Calais'), ); calais_build_entity_settings($form["calais_{$key}_settings"], $key, $name, true); } } /** * Have to override so that we can manage vocabulary - node_type relationships. * * @param unknown_type $form_id * @param unknown_type $form_state */ function calais_admin_settings_submit($form, &$form_state) { system_settings_form_submit($form, $form_state); // Also, set vocabulary-node relationships $node_types = node_get_types('types', NULL, TRUE); $all_vocabularies = calais_get_entity_vocabularies(); foreach ($node_types as $nt) { $key = strtolower($nt->type); $state = variable_get('calais_node_'. $key .'_process', CALAIS_PROCESS_NO); foreach ($all_vocabularies as $entity => $vid) { // Clean-up db_query("DELETE FROM {vocabulary_node_types} WHERE vid='%d' and type='%s'", $vid, $key); } if ($state !== CALAIS_PROCESS_NO) { // assign all configured calais vocabs to this node type $node_vocabularies = calais_get_entity_vocabularies($key); foreach ($node_vocabularies as $entity => $vid) { db_query("INSERT INTO {vocabulary_node_types} (vid, type) values('%d','%s') ", $vid, $key); } } } } /** * Implementation of hook_nodeapi(). * * Process node updates and if applicable, update the Calais terms. */ function calais_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { switch ($op) { case "delete": db_query("DELETE FROM {calais_term_node} WHERE nid=%d", $node->nid); break; case "insert": case "update": if (calais_processing_type($node) == CALAIS_PROCESS_NO) return; cache_clear_all(); $data = "$node->title \n $node->body"; $node_settings = calais_get_node_settings($node); $keywords = calais_api_analyze($node, $data, $node_settings); if (sizeof($keywords) > 0) { db_query("DELETE FROM {calais_term_node} WHERE nid=%d", $node->nid); } module_invoke_all('calais_preprocess', $node, &$keywords); $vocabularies = calais_get_entity_vocabularies($node->type); foreach ($keywords as $cat => $terms) { $vid = $vocabularies[$cat]; foreach ($terms as $term) { $term = trim($term); $tid = calais_verify_and_get_term($vid, $term, 'calais'); if ($tid) { calais_assign_node_calaisterm($node->nid, $tid); } else { watchdog('Calais', "Could not create Calais Term: $term"); } //-- Auto-assign Taxonomy Terms if (calais_processing_type($node) == CALAIS_PROCESS_AUTO) { $tid = calais_verify_and_get_term($vid, $term, 'taxonomy'); if ($tid) { calais_assign_node_taxonomyterm($node->nid, $node->vid, $tid); } else { watchdog('Calais', "Could not assign Taxonomy Term: $term"); } } } } module_invoke_all('calais_postprocess', $node, $keywords); break; } } /** * Implementation of hook_calais_preprocess. * * Make sure that a vocabulary exists for all entities returned, if not, create it. */ function calais_calais_preprocess($node, &$keywords) { $vocabularies = calais_get_entity_vocabularies(); foreach ($keywords as $cat => $terms) { $vid = $vocabularies[$cat]; // Create a vocabulary if we come across an entity that we dont know of. if (!$vid) { $vid = calais_create_entity_vocabulary($cat); $vocabularies[$cat] = $vid; variable_set('calais_vocabulary_names', $vocabularies); drupal_set_message(t('Added a Vocabulary for the new Calais Entity %entity. You may need to update your Calais Node Settings to take advantage of this new entity.', array('%entity' => $cat))); } } } /** * Checks if a specified term exists in a specified vocabulary. * If it does not exist - creates it. * * @param int $vid * @param name $term * * @return int $tid Term id in {calais_term} table */ function calais_verify_and_get_term($vid, $term, $module) { switch ($module) { case 'calais': $tablename = "calais_term"; break; case 'taxonomy': $tablename = 'term_data'; break; default: return NULL; } $bool = false; $term = trim($term); $bool = db_result(db_query("SELECT count(*) FROM {".$tablename."} where name='%s' and vid=%d", $term, $vid)); if (!$bool) { $form_values = array('vid' => $vid, 'name' => $term); switch ($module) { case 'calais': db_query("INSERT INTO {".$tablename."}(name,vid) values('%s',%d)", $term, $vid); break; case 'taxonomy': taxonomy_save_term($form_values); break; } } $tid = db_result(db_query("SELECT tid FROM {".$tablename."} WHERE name='%s' and vid=%d", $term, $vid)); cache_clear_all(); return $tid; } function calais_assign_node_calaisterm($nid, $tid) { db_query("DELETE FROM {calais_term_node} where nid=%d and tid=%d", $nid, $tid); db_query("INSERT INTO {calais_term_node} (nid, tid) VALUES(%d, %d)", $nid, $tid); } function calais_assign_node_taxonomyterm($nid, $vid, $tid) { db_query("DELETE FROM {term_node} where nid=%d and vid=%d and tid=%d", $nid, $vid, $tid); db_query("INSERT INTO {term_node} (nid, vid, tid) VALUES(%d, %d, %d)", $nid, $vid, $tid); } /** * Determines which processing type (none, manual, auto) is * applicable to a node specific node instance passed as an argument. * * @param mixed $var either a Node object or a valid node_type String * * @return constant one of: CALAIS_PROCESS_NO, CALAIS_PROCESS_AUTO or CALAIS_PROCESS_MANUAL */ function calais_processing_type($var) { if (is_object($var)) { $nodetype = $var->type; } else { $nodetype = $var; } $key = strtolower($nodetype); return variable_get('calais_node_'. $key .'_process', CALAIS_PROCESS_NO); } /** * Return the Calais parameter settings for the specific node type. */ function calais_get_node_settings($node) { $settings = array( 'allowSearch' => variable_get("calais_api_allow_searching_{$node->type}", false) ? 'true' : 'false', 'allowDistribution' => variable_get("calais_api_allow_distribution_{$node->type}", false) ? 'true' : 'false', ); return $settings; } /** * Get a list of the entities that Calais API defines: * http://opencalais.mashery.com/page/calaissemanticmetadata * * IF $type is not specified it will return all known Calais Entities. * however if $type is specified it will return only those Entities that the * specific node type is interested in, or the global list if no specific node type * settings have been configures. * * @param $type - A node type, if Entities need to be filtered. * * @return Associative array of [entity_name => vid]'s */ function calais_get_entity_vocabularies($type = NULL) { $all_vocabs = variable_get('calais_vocabulary_names', false); if ($type) { $applied_entities = variable_get('calais_applied_entities_global', false); if (!variable_get("calais_use_global_{$type}", true)) { $applied_entities = variable_get("calais_applied_entities_{$type}", false); } foreach ($applied_entities as $entity => $apply_entity) { if ($apply_entity) { $applied_vocabs[$entity] = $all_vocabs[$entity]; } } } else { $applied_vocabs = $all_vocabs; } return $applied_vocabs; } /** * Returns the Calais vocabularies that are enabled for this node type. *

Compare to: calais_api_get_all_entities() which gives entityname/vid pairs. * Vocabulary names can be updated by users. Entity names stay as defined * by Calais. * * @param $node_type The node type * * @return Array of vocabularies keyed on vid; */ function calais_get_vocabularies($type = NULL) { $vocs = calais_get_entity_vocabularies($type); $pattern = implode(",", $vocs); if ($type) { $result = db_query("SELECT v.vid, v.*, n.type FROM {vocabulary} v LEFT JOIN {vocabulary_node_types} n ON v.vid = n.vid WHERE n.type = '%s' and v.vid in (%s) ORDER BY v.weight, v.name", $type, $pattern); } else { $result = db_query('SELECT v.* FROM {vocabulary} v WHERE v.vid in (%s) ORDER BY v.weight, v.name', $pattern); } $vocabularies = array(); $node_types = array(); while ($voc = db_fetch_object($result)) { // If no node types are associated with a vocabulary, the LEFT JOIN will // return a NULL value for type. if (isset($voc->type)) { $node_types[$voc->vid][$voc->type] = $voc->type; unset($voc->type); $voc->nodes = $node_types[$voc->vid]; } elseif (!isset($voc->nodes)) { $voc->nodes = array(); } $vocabularies[$voc->vid] = $voc; } return $vocabularies; } /** * Returns a map of suggested terms for a given vocabulary id. This will return * sugested terms for all vocabularies if no vid is specified. * * @param $nid The node id to get the calais keywords * @param $vid Optional, a specific vocabulary id to return terms * * @return Array { $vid => array('term1', 'term2', 'term3') } */ function calais_get_keywords($nid, $vid = null) { $terms = array(); if ($vid) { $res = db_query(" SELECT name FROM {calais_term} t JOIN {calais_term_node} tn ON tn.tid=t.tid WHERE tn.nid=%d and t.vid=%d ORDER BY name asc ", $nid, $vid); $terms[$vid] = array(); while ($obj = db_fetch_object($res)) { $terms[$vid][] = $obj->name; } } else { $vocabularies = calais_get_entity_vocabularies(); foreach ($vocabularies as $vid) { $keys = calais_get_keywords($nid, $vid = null); $terms[$vid] = $keys[$vid]; } } return $terms; } /** * Creates a new vocabulary for the supplied Calais entity name. */ function calais_create_entity_vocabulary($entity) { $description = t("Calais Entity Vocabulary: @name", array('@name' => $entity)); db_query("INSERT INTO {vocabulary} (name,description,module,tags) values('%s','%s','taxonomy',1)", $entity, $description); return db_last_insert_id('vocabulary', 'vid'); } function ____debug($array, $exit = true) { echo "

". print_r($array, true) ."
"; if ($exit) exit(0); }