t('Meta tags'), 'description' => t('Meta tags fieldset.'), 'weight' => 10, ); return $extras; } /** * Implementation of hook_form_alter(). */ function nodewords_form_alter(&$form, &$form_state, $form_id) { $bool = ( isset($form['type']) && isset($form['type']['#value']) && $form_id == $form['type']['#value'] . '_node_form' && variable_get('nodewords_edit_metatags_' . $form['type']['#value'], TRUE) ); if ($bool) { $id = $form['nid']['#value']; if (!empty($form_state['values']['nodewords'])) { $tags = $form_state['values']['nodewords']; } elseif (isset($id) && is_numeric($id)) { $tags = nodewords_load_tags(NODEWORDS_MT_TYPE_NODE, $id); } else { $tags = array(); } $form['nodewords'] = nodewords_form( NODEWORDS_MT_TYPE_NODE, $tags, array( 'page:permissions:additional' => 'administer nodes', 'tag_options' => array('node_type' => $form['type']['#value']), ) ); } } /** * Implementation of hook_form_FORM_ID_alter(). */ function nodewords_form_node_type_form_alter(&$form, &$form_state) { if (isset($form['#node_type'])) { $form['nodewords'] = array( '#type' => 'fieldset', '#title' => t('Meta tags settings'), '#collapsible' => TRUE, '#collapsed' => TRUE, ); $form['nodewords']['nodewords_edit_metatags'] = array( '#type' => 'checkbox', '#title' => t('Allow editing of meta tags'), '#description' => t('If selected, the node edit form will allow the users with the right permissions to edit the meta tags associated with nodes of this content type.'), '#default_value' => variable_get('nodewords_edit_metatags_' . $form['#node_type']->type, TRUE), ); foreach (nodewords_get_possible_tags() as $name => $info) { $function = $info['tag:function:prefix'] . '_settings_form'; $options = array( 'parameters' => !empty($info['tag:function:parameters']) ? $info['tag:function:parameters'] : array(), ); if (function_exists($function)) { $function($form, 'node_type_form', $options); } } } } /** * Implementation of hook_form_FORM_ID_alter(). */ function nodewords_form_taxonomy_form_term_alter(&$form, &$form_state) { $bool = (isset($form['tid']['#value']) && !isset($form_state['confirm_delete']) && !isset($form_state['confirm_parents']) ); if ($bool) { $id = $form['tid']['#value']; if (!empty($form_state['values']['nodewords'])) { $tags = $form_state['values']['nodewords']; } elseif (isset($id) && is_numeric($id)) { $tags = nodewords_load_tags(NODEWORDS_MT_TYPE_TERM, $id); } else { $tags = array(); } $form['nodewords'] = nodewords_form( NODEWORDS_MT_TYPE_TERM, $tags, array() ); $form['submit']['#weight'] = 45; $form['delete']['#weight'] = 50; } } /** * Implementation of hook_form_FORM_ID_alter(). */ function nodewords_form_taxonomy_form_vocabulary_alter(&$form, &$form_state) { if (isset($form['vid']['#value'])) { $id = $form['vid']['#value']; if (!empty($form_state['values']['nodewords'])) { $tags = $form_state['values']['nodewords']; } elseif (isset($id) && is_numeric($id)) { $tags = nodewords_load_tags(NODEWORDS_MT_TYPE_VOCABULARY, $id); } else { $tags = array(); } $form['nodewords'] = nodewords_form( NODEWORDS_MT_TYPE_VOCABULARY, $tags, array() ); $form['submit']['#weight'] = 45; $form['delete']['#weight'] = 50; } } /** * Implemenation of hook_help(). */ function nodewords_help($path, $arg) { switch ($path) { case 'admin/content/nodewords/meta-tags': $output = '

' . t('On this page you can enter the default values for the meta tags of your site.') . '

'; break; case 'admin/content/nodewords/meta-tags/errorpage_403': $output = '

' . t('On this page you can enter the meta tags for the access denied error page of your site.') . '

'; break; case 'admin/content/nodewords/meta-tags/errorpage_404': $output = '

' . t('On this page you can enter the meta tags for the page not found error page of your site.') . '

'; break; case 'admin/content/nodewords/meta-tags/frontpage': $output = '

' . t('On this page you can enter the meta tags for the front page of your site.') . '

'; break; case 'admin/content/nodewords/meta-tags/other': $output = '

' . t('On this page you can enter the meta tags for other pages of your site. Add meta tags for a new page.', array('@add_metatags' => url('admin/content/nodewords/meta-tags/other/add'))) . '

'; break; case 'admin/content/nodewords/meta-tags/pager': $output = '

' . t('On this page you can enter the meta tags for pages that are part of a pager. This values will be used only when the option %option in the settings page is not selected.', array('%option' => t('Repeat meta tags for lists'), '@settings_page' => url('admin/content/nodewords/settings'))) . '

'; break; case 'admin/content/nodewords/meta-tags/tracker': $output = '

' . t('On this page you can enter the meta tags for tracker pages of your site.') . '

'; break; default: $output = ''; break; } return $output; } /** * Implementation of hook_menu(). */ function nodewords_menu() { $admin_access = array('administer meta tags'); $items = array(); $items['admin/content/nodewords'] = array( 'title' => 'Meta tags', 'page callback' => 'drupal_get_form', 'page arguments' => array('nodewords_settings_form'), 'description' => 'Configure HTML meta tags for all the content.', 'access arguments' => $admin_access, 'type' => MENU_NORMAL_ITEM, 'file' => 'nodewords.admin.inc', ); $items['admin/content/nodewords/settings'] = array( 'title' => 'Settings', 'access arguments' => $admin_access, 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -1, 'file' => 'nodewords.admin.inc', ); $items['admin/content/nodewords/meta-tags'] = array( 'title' => 'Default and specific meta tags', 'page callback' => 'drupal_get_form', 'page arguments' => array('nodewords_tags_form'), 'access arguments' => $admin_access, 'type' => MENU_LOCAL_TASK, 'file' => 'nodewords.admin.inc', ); $items['admin/content/nodewords/meta-tags/default'] = array( 'title' => 'Default values', 'access arguments' => $admin_access, 'type' => MENU_DEFAULT_LOCAL_TASK, 'file' => 'nodewords.admin.inc', ); $items['admin/content/nodewords/meta-tags/errorpage_403'] = array( 'title' => 'Error 403 page', 'page callback' => 'drupal_get_form', 'page arguments' => array('nodewords_tags_form', NODEWORDS_MT_TYPE_ERRORPAGE, '403'), 'access arguments' => $admin_access, 'type' => MENU_LOCAL_TASK, 'file' => 'nodewords.admin.inc', ); $items['admin/content/nodewords/meta-tags/errorpage_404'] = array( 'title' => 'Error 404 page', 'page callback' => 'drupal_get_form', 'page arguments' => array('nodewords_tags_form', NODEWORDS_MT_TYPE_ERRORPAGE, '404'), 'access arguments' => $admin_access, 'type' => MENU_LOCAL_TASK, 'file' => 'nodewords.admin.inc', ); $items['admin/content/nodewords/meta-tags/frontpage'] = array( 'title' => 'Front page', 'page callback' => 'drupal_get_form', 'page arguments' => array('nodewords_tags_form', NODEWORDS_MT_TYPE_FRONTPAGE), 'access arguments' => $admin_access, 'type' => MENU_LOCAL_TASK, 'file' => 'nodewords.admin.inc', ); $items['admin/content/nodewords/meta-tags/pager'] = array( 'title' => 'Pager', 'page callback' => 'drupal_get_form', 'page arguments' => array('nodewords_tags_form', NODEWORDS_MT_TYPE_PAGER), 'access arguments' => $admin_access, 'type' => MENU_LOCAL_TASK, 'file' => 'nodewords.admin.inc', ); $items['admin/content/nodewords/meta-tags/tracker'] = array( 'title' => 'Tracker pages', 'page callback' => 'drupal_get_form', 'page arguments' => array('nodewords_tags_form', NODEWORDS_MT_TYPE_TRACKER), 'access arguments' => $admin_access, 'type' => MENU_LOCAL_TASK, 'file' => 'nodewords.admin.inc', ); $items['admin/content/nodewords/meta-tags/other'] = array( 'title' => 'Other pages', 'page callback' => 'drupal_get_form', 'page arguments' => array('nodewords_pages_overview'), 'access arguments' => $admin_access, 'type' => MENU_LOCAL_TASK, 'weight' => 5, 'file' => 'nodewords.admin.inc', ); $items['admin/content/nodewords/meta-tags/other/add'] = array( 'title' => 'Add page meta tags', 'page callback' => 'drupal_get_form', 'page arguments' => array('nodewords_pages_edit'), 'access arguments' => $admin_access, 'type' => MENU_CALLBACK, 'file' => 'nodewords.admin.inc', ); $items['admin/content/nodewords/meta-tags/other/delete/%nodewords_page'] = array( 'title' => 'Delete page meta tags', 'page callback' => 'drupal_get_form', 'page arguments' => array('nodewords_pages_confirm_delete', 6), 'access arguments' => $admin_access, 'parent' => 'admin/content/nodewords/meta-tags/other', 'type' => MENU_CALLBACK, 'file' => 'nodewords.admin.inc', ); $items['admin/content/nodewords/meta-tags/other/edit/%nodewords_page'] = array( 'title' => 'Edit page meta tags', 'page callback' => 'drupal_get_form', 'page arguments' => array('nodewords_pages_edit', 6), 'access arguments' => $admin_access, 'parent' => 'admin/content/nodewords/meta-tags/other', 'type' => MENU_CALLBACK, 'file' => 'nodewords.admin.inc', ); return $items; } /** * Implementation of hook_node_operations(). */ function nodewords_node_operations() { $operations = array( 'delete_metatags' => array( 'label' => t('Delete meta tags'), 'callback' => 'nodewords_mass_delete_tags', 'callback arguments' => array('type' => NODEWORDS_MT_TYPE_NODE), ), ); return $operations; } /** * Implementation of hook_nodeapi(). */ function nodewords_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) { switch ($op) { case 'delete': nodewords_delete_tags(NODEWORDS_MT_TYPE_NODE, $node->nid); break; case 'insert': case 'update': if (isset($node->nodewords)) { nodewords_save_tags(NODEWORDS_MT_TYPE_NODE, $node->nid, $node->nodewords, TRUE); } break; case 'update index': $output = ''; if (isset($node->nodewords)) { $tags_info = nodewords_get_possible_tags(); foreach ($node->nodewords as $name => $content) { // Avoid the disabled meta tags. if (!isset($info[$name])) { continue; } if (!empty($tags_info[$name]['tag:template:index'])) { $output .= strtr($tags_info[$name]['tag:template:index'], '%content', $content); } } } return $output; case 'load': return array( 'nodewords' => nodewords_load_tags(NODEWORDS_MT_TYPE_NODE, $node->nid), ); } } /** * Implementation of hook_perm(). */ function nodewords_perm() { return array('administer meta tags'); } /** * Implementation of hook_preprocess_page(). */ function nodewords_preprocess_page(&$variables) { list($type, $ids) = _nodewords_detect_type_and_ids(); drupal_set_html_head(nodewords_output_tags(nodewords_get_tags($type, $ids))); $variables['head'] = drupal_get_html_head(); } /** * Implementation of hook_taxonomy(). */ function nodewords_taxonomy($op, $type, $object = NULL) { if ($type == 'term') { $id = $object['tid']; $type = NODEWORDS_MT_TYPE_TERM; } elseif ($type == 'vocabulary') { $id = $object['vid']; $type = NODEWORDS_MT_TYPE_VOCABULARY; } else { return; } switch ($op) { case 'delete': nodewords_delete_tags($type, $id); break; case 'insert': case 'update': if (isset($object['nodewords'])) { nodewords_save_tags($type, $id, $object['nodewords'], TRUE); } break; } } /** * Implementation of hook_theme(). */ function nodewords_theme() { return array( 'nodewords_pages_overview' => array( 'arguments' => array('form' => array()), ), ); } /** * Implementation of hook_user(). */ function nodewords_user($op, &$edit, &$account, $category = NULL) { switch ($op) { case 'load': if (variable_get('nodewords_enable_user_metatags', TRUE)) { $account->nodewords = nodewords_load_tags(NODEWORDS_MT_TYPE_USER, $account->uid); } break; case 'delete': nodewords_delete_tags(NODEWORDS_MT_TYPE_USER, $account->uid); break; case 'insert': case 'update': if (isset($edit['nodewords'])) { nodewords_save_tags(NODEWORDS_MT_TYPE_USER, $account->uid, $edit['nodewords'], TRUE); } break; case 'form': if ($category == 'account') { if (variable_get('nodewords_enable_user_metatags', TRUE)) { $tags = nodewords_load_tags(NODEWORDS_MT_TYPE_USER, $account->uid); $form['nodewords'] = nodewords_form( NODEWORDS_MT_TYPE_USER, $tags, array( 'page:permissions:additional' => 'administer users', ) ); return $form; } } break; } } /** * Implementation of hook_user_operations(). */ function nodewords_user_operations() { $operations = array( 'delete_metatags' => array( 'label' => t('Delete meta tags'), 'callback' => 'nodewords_mass_delete_tags', 'callback arguments' => array('type' => NODEWORDS_MT_TYPE_USER), ), ); return $operations; } /***************************************************************************** * Public functions. ****************************************************************************/ /** * Delete tags from table. */ function nodewords_delete_tags($type, $id) { db_query("DELETE FROM {nodewords} WHERE type = %d AND id = '%s'", $type, $id); if ($type == NODEWORDS_MT_TYPE_PAGE) { db_query("DELETE FROM {nodewords_custom} WHERE path = '%s'", $id); } } /** * Return the form used to set the meta tags values. * * @param $type * The object to which the meta tags are associated (node, user, taxonomy * term, etc...). * @param $tags * The meta tags array as returned by nodewords_load_tags(). * * @return * An array as requested by the form API. */ function nodewords_form($type, $tags, $options = array()) { $default_options = array( 'fieldset' => TRUE, 'fieldset:title' => t('Meta tags'), 'fieldset:weight' => 20, ); $edit_tags = variable_get('nodewords_edit', array()); $form = array(); $options += $default_options; $tag_options = array( 'default' => nodewords_load_tags(), 'type' => $type, ); $tags_info = nodewords_get_possible_tags(); $token_module_enabled = module_exists('token'); $tokens_support = FALSE; if (isset($options['tag_options'])) { $tag_options = array_merge($options['tag_options'], $tag_options); } foreach ($tags_info as $name => $info) { if (empty($edit_tags[$name])) { continue; } if (!empty($info['tag:context:allowed'])) { $bool = ( in_array('', $info['tag:context:allowed']) || !in_array($type, $info['tag:context:allowed']) ); if ($bool) { continue; } } elseif (!empty($info['tag:context:denied'])) { if (in_array($type, $info['tag:context:denied'])) { continue; } } $bool = ( ( !empty($options['page:permissions:additional']) && user_access($options['page:permissions:additional']) ) || ( !empty($info['widget:permission']) && user_access($info['widget:permission']) ) ); if ($bool) { if (function_exists($function = $info['tag:function:prefix'] . '_form')) { $tag_options['parameters'] = !empty($info['tag:function:parameters']) ? $info['tag:function:parameters'] : array(); $function($form, isset($tags[$name]) ? $tags[$name] : array(), $tag_options); } } } if (!empty($form)) { _nodewords_cmp_form_fields($form, 0, TRUE); uksort($form, '_nodewords_cmp_form_fields'); if ($options['fieldset']) { $collapsed = FALSE; foreach (element_children($form) as $id) { if ($form[$id]['#type'] == 'fieldset') { if (!empty($form[$id]['#collapsed'])) { $collapsed = TRUE; } if ($token_module_enabled && !empty($tags_info[$id]['tag:tokens'])) { $tokens_support = TRUE; $tokens_support_str = t('This meta tag supports tokens.'); if (empty($form[$id]['#description'])) { $form[$id]['#description'] = $tokens_support_str; } else { $form[$id]['#description'] .= ' ' . $tokens_support_str; } } } } if ($tokens_support && type != NODEWORDS_MT_TYPE_DEFAULT) { switch ($type) { case NODEWORDS_MT_TYPE_ERRORPAGE: case NODEWORDS_MT_TYPE_FRONTPAGE: case NODEWORDS_MT_TYPE_PAGER: case NODEWORDS_INSTALL_MT_TYPE_TRACKER: $token_type = 'global'; break; case NODEWORDS_MT_TYPE_NODE: $token_type = 'node'; break; case NODEWORDS_MT_TYPE_USER: $token_type = 'user'; break; default: $token_type = ''; break; } if (!empty($token_type)) { $form['nodewords_token_help'] = array( '#title' => t('Replacement patterns'), '#type' => 'fieldset', '#collapsible' => TRUE, '#collapsed' => TRUE, '#description' => t('Prefer raw-text replacements for text to avoid problems with HTML entities!'), ); $form['nodewords_token_help']['help'] = array( '#value' => theme('token_help', 'node'), ); } } $form['#type'] = 'fieldset'; $form['#title'] = $options['fieldset:title']; $form['#tree'] = TRUE; $form['#collapsible'] = TRUE; $form['#collapsed'] = variable_get('nodewords_collapse_fieldset', FALSE) || $collapsed; $form['#weight'] = $options['fieldset:weight']; } } return $form; } /** * Return a list of possible output tags. * * @param $remove_disabled * If TRUE, disabled meta tags will not be returned. * * @return * An array containing the list of meta tags. */ function nodewords_get_possible_tags() { static $tags_info; if (!isset($tags_info)) { $tags_info = array(); // Allow third-party modules to alter the meta tags list, or to add new // meta tags. foreach (module_implements('nodewords_tags_info') as $module) { if (module_hook($module, 'nodewords_api')) { $result = module_invoke($module, 'nodewords_api'); if (isset($result)) { if (is_numeric($result)) { if ($result <> NODEWORDS_API_VERSION) { continue; } } elseif (is_array($result) && isset($result['version'])) { if ($result['version'] <> NODEWORDS_API_VERSION) { continue; } } else { continue; } } else { continue; } $result = module_invoke($module, 'nodewords_tags_info'); if (isset($result) && is_array($result)) { $tags_info = array_merge($tags_info, $result); } } } } return $tags_info; } /** * Get the defined meta tags for $type / $id. * * @param $type * Realm of the object the meta tags are associated with. * This is one of the following: NODEWORDS_MT_TYPE_ERRORPAGE, NODEWORDS_MT_TYPE_FRONTPAGE, NODEWORDS_MT_TYPE_NODE, * NODEWORDS_MT_TYPE_PAGE, NODEWORDS_MT_TYPE_PAGER, NODEWORDS_MT_TYPE_TERM, NODEWORDS_MT_TYPE_TRACKER, NODEWORDS_MT_TYPE_VOCABULARY. * @param $ids * ID of the object to get the meta tags from. * This is one of the following: * - NODEWORDS_MT_TYPE_ERRORPAGE => an array containing the HTML error code (403 or 404). * - NODEWORDS_MT_TYPE_FRONTPAGE => none. * - NODEWORDS_MT_TYPE_NODE => an array containing the node ID. * - NODEWORDS_MT_TYPE_PAGE => an array containing the page path. * - NODEWORDS_MT_TYPE_TERM => an array of term IDs. * - NODEWORDS_MT_TYPE_USER => an array containing the user ID. * - NODEWORDS_MT_TYPE_VOCABULARY => an array of vocabulary IDs. * @param $filtered * If TRUE, only the meta tags that the user configured for * output will be returned. * If FALSE, all meta tags will be returned. * * @return * An associative array of the defined meta tags. */ function nodewords_get_tags($type, $ids = array(''), $filtered = TRUE) { $output_tags = array(); $tag_options = array( 'default' => nodewords_load_tags(), 'ids' => $ids, 'type' => $type, ); if (!is_array($ids)) { $ids = array($ids); } if ($type == NODEWORDS_MT_TYPE_PAGER) { foreach (nodewords_get_possible_tags() as $name => $info) { if (!empty($info['tag:pager']) && function_exists($function = $info['tag:function:prefix'] . '_prepare')) { $tag_options['parameters'] = !empty($info['tag:function:parameters']) ? $info['tag:function:parameters'] : array(); $function($output_tags, array(), $tag_options); } } } else { // User profiles metatags are not enabled. if ($type == NODEWORDS_MT_TYPE_USER && !variable_get('nodewords_enable_user_metatags', TRUE)) { $tags = array(); } // Load the values from the database elseif (count($ids) == 1 && ($type != NODEWORDS_MT_TYPE_NODE || node_access('view', node_load($ids[0])))) { $tags = nodewords_load_tags($type, $ids[0]); } else { $tags = array(); } // Prepare the tags. foreach (nodewords_get_possible_tags() as $name => $info) { if (function_exists($function = $info['tag:function:prefix'] . '_prepare')) { $tag_options['parameters'] = !empty($info['tag:function:parameters']) ? $info['tag:function:parameters'] : array(); $function($output_tags, isset($tags[$name]) ? $tags[$name] : array(), $tag_options); } } } // Filter out tags the user has chosen not to see if ($filtered) { foreach (variable_get('nodewords_head', array()) as $name => $viewable) { if (!$viewable) { unset($output_tags[$name]); } } } return $output_tags; } /** * Return the term object matching a term ID. This is a modified version of * taxonomy_get_term() which uses db_rewrite_sql(). * * @param $tid * A term's ID. * * @return * A term object. Results are statically cached. */ function nodewords_get_term($tid) { global $user; static $previous_uid = -1, $terms = array(); if ($user->uid <> $previous_uid) { $terms = array(); $previous_uid = $user->uid; } if (!isset($terms[$tid])) { $terms[$tid] = db_fetch_object( db_query( db_rewrite_sql('SELECT * FROM {term_data} t WHERE t.tid = %d', 't', 'tid'), $tid ) ); } return $terms[$tid]; } /** * Load tags from table. */ function nodewords_load_tags($type = NODEWORDS_MT_TYPE_DEFAULT, $id = '') { $result = db_query("SELECT * FROM {nodewords} WHERE type = %d AND id = '%s'", $type, $id); $tags = array(); $tags_info = nodewords_get_possible_tags(); while ($row = db_fetch_object($result)) { if (isset($tags_info[$row->name])) { $tags[$row->name] = $tags_info[$row->name]['tag:db:type'] != 'string' ? unserialize($row->content) : array('value' => $row->content); } } if (empty($tags) && $type == NODEWORDS_MT_TYPE_TERM) { return nodewords_load_tags(NODEWORDS_MT_TYPE_VOCABULARY, db_result(db_query('SELECT vid FROM {term_data} WHERE tid = %d', $id))); } return $tags; } /** * Delete the nodes meta tags. * * @param $ids * An array of IDs. * @param $type * The type of the object associated with the IDs (NODEWORDS_MT_TYPE_NODE, * NODEWORDS_MT_TYPE_USER, ...). */ function nodewords_mass_delete_tags($ids, $type) { db_query("DELETE FROM {nodewords} WHERE id IN (" . db_placeholders($ids, 'varchar') . ") AND type = %d", array_merge($ids, array($type)) ); if ($type == NODEWORDS_MT_TYPE_PAGE) { db_query("DELETE FROM {nodewords_custom} WHERE path IN (" . db_placeholders($ids, 'varchar') . ")", $ids ); } drupal_set_message(t('The update has been performed.')); } /** * Create the content of a meta tag from a node teaser. * * @param $body * The node body. * @param $format * The format set for the node. * @param $alt_attribute * If TRUE, any tag img will be replaced with its attribute alt. * @param $size * The maximum allowed size; if it is zero, then the function will use the * value of the Drupal variable nodewords_max_size. * * @return * The string to use to populate the meta tag. */ function nodewords_metatag_from_teaser($body, $format, $alt_attribute, $size = 0) { if (!$size) { $size = variable_get('nodewords_max_size', 350); } // We check for the presence of the PHP evaluator filter in the current // format. If the body contains PHP code, we do not split it up to prevent // parse errors. if (isset($format)) { $filters = filter_list_format($format); if (isset($filters['php/0']) && strpos($body, '')) !== FALSE) { $body = substr($body, 0, $delimiter); } // Initialize the helper function used for preg_replace_callback. _nodewords_teaser_match_callback($alt_attribute, TRUE); // Replace the meta tag img with the attribute alt, and strip off all the // HTML tags. $body = strip_tags( preg_replace_callback('/]*alt=["\']([^"\']*)["\'][^>]*>/i', '_nodewords_teaser_match_callback', $body ) ); // Truncate the string at last space within the given size. return truncate_utf8($body, $size, TRUE); } /** * Render the meta tag values as HTML. * * @param $tags * An array of tags (as returned by nodewords_get_tags()). * * @return * A string containing the HTML output for the META tag. */ function nodewords_output_tags($tags) { $output = array(); $tags_info = nodewords_get_possible_tags(); $weights = array(); foreach ($tags as $name => $content) { if (empty($content)) { continue; } $parts = explode(':', $name); if (!isset($parts[1])) { $parts[1] = $parts[0]; } $bool = ( isset($tags_info[$parts[0]]['tag:template'][$parts[1]]) && ($meta_name = check_plain(strip_tags(decode_entities($parts[1])))) && ($meta_content = check_plain(strip_tags(decode_entities($content)))) ); if ($bool) { $replace = array( '%name' => $meta_name, '%content' => $meta_content, '%attributes' => empty($tags_info[$parts[0]]['tag:attributes'][$parts[1]]) ? '' : drupal_attributes($tags_info[$parts[0]]['tag:attributes'][$parts[1]]), ); $template = $tags_info[$parts[0]]['tag:template'][$parts[1]]; $weight = isset($tags_info[$parts[0]]['tag:weight'][$parts[1]]) ? $tags_info[$parts[0]]['tag:weight'][$parts[1]] : 0; switch ($template) { case NODEWORDS_META: $template = ''; break; case NODEWORDS_HTTP_EQUIV: $template = ''; break; case NODEWORDS_LINK_REL: $template = ''; break; case NODEWORDS_LINK_REV: $template = ''; break; default: if (!is_string($template)) { $template = ''; } break; } if (!empty($template)) { $output[] = strtr($template, $replace); $weights[] = $weight; } } } array_multisort($weights, $output); return implode("\n", $output); } /** * This function is used from the menu system when a menu callback path contains * %nodewords_page_load. */ function nodewords_page_load($pid) { return _nodewords_get_pages_data($pid); } function nodewords_replace_tokens($type, $id, $content) { if (empty($content) || !module_exists('token')) { return $content; } switch ($type) { case NODEWORDS_MT_TYPE_ERRORPAGE: case NODEWORDS_MT_TYPE_FRONTPAGE: case NODEWORDS_MT_TYPE_PAGER: case NODEWORDS_INSTALL_MT_TYPE_TRACKER: $token_type = 'global'; $token_object = NULL; break; case NODEWORDS_MT_TYPE_NODE: if (is_array($id) && isset($id[0])) { $id = $id[0]; } $token_type = 'node'; $token_object = node_load(array('vid' => $id)); break; case NODEWORDS_MT_TYPE_USER: if (is_array($id) && isset($id[0])) { $id = $id[0]; } $token_type = 'user'; $token_object = user_load($id); break; default: return $content; } return token_replace($content, $token_type, $token_object); } /** * Update or insert tags in the table. */ function nodewords_save_tags($type, $id, $tags, $log_message = FALSE) { global $user; static $tags_info; if (!isset($tags_info)) { $tags_info = nodewords_get_possible_tags(); } $done = FALSE; foreach ($tags as $name => $content) { if (isset($tags_info[$name])) { if ($tags_info[$name]['tag:db:type'] != 'string') { $content = serialize($content); } else { $content = $content['value']; } $result = db_fetch_object(db_query("SELECT * FROM {nodewords} WHERE type = %d AND id = '%s' AND name = '%s'", $type, $id, $name)); if ($result === FALSE) { $row = new stdClass(); $row->type = $type; $row->id = $id; $row->name = $name; } else { $row = $result; } $row->content = $content; drupal_write_record('nodewords', $row, $result !== FALSE ? 'mtid' : NULL); if (!$done) { watchdog('nodewords', '%name changed the meta tags for %type (%id).', array('%name' => $user->name, '%type' => $type, '%id' => $id)); $done = TRUE; } } } } /* * Remove the duplicates from a list of items separated from the separator, * preserving the order in which they appear. * @param $text * The string containing the list of items concatenated using $separator. * @param $separator * The string used to split the string into an array. A space will be appended * to the string before it is used to create the string from the array of * unique items found in the string passed as argument. * @param $max_items * The maximum number of items accepted in the returned array; the default * value is -1, which means no limit. * * @return * A string containing only unique items present in the string of concatenated * items. */ function nodewords_unique($text, $separator = ',', $max_items = -1) { $lc_values = array(); $unique_values = array(); if (empty($text)) { return ''; } foreach (array_filter(array_map('trim', explode($separator, $text))) as $item) { $lowercase = drupal_strtolower($item); if (!in_array($lowercase, $lc_values)) { $lc_values[] = $lowercase; $unique_values[] = $item; } } if ($max_items > 0) { $unique_values = array_slice($uniq_values, 0, $max_items); } return implode("$separator ", $unique_values); } /***************************************************************************** * Private functions. ****************************************************************************/ /** * Show the requirement errors reported from nodewords_requirements(). * The function is an adaption of drupal_check_module(), and it is called in * the module settings pages. */ function _nodewords_check_enabled_modules() { function _nodewords_check_enabled_modules() { if (user_access('administer site configuration')) { if (!count(module_implements('nodewords_api'))) { drupal_set_message( t( 'Nodewords does not create meta tags anymore; it is just a module that implements a public API used from the modules that create meta tags. You need to enable at least one module between nodewords_basic.module, nodewords_extra.module, and nodewords_verification_tags.module that are listed under Meta tags in the modules page.', array('@url' => url('admin/build/modules')) ), 'error' ); } if (module_exists('nodewords_bypath')) { drupal_set_message( t( 'The feature implemented in Meta Tags by Path is now included in Nodewords; there is not need to use Meta Tags by Path, and the module should be disabled to avoid possible conflicts. Disable the module in themodules page.'), array('@url' => url('admin/build/modules') ) ); } } } } /** * Helper function for uksort(). * Sort the form fields basing on their titles. */ function _nodewords_cmp_form_fields($a, $b, $init = FALSE) { static $form; if ($init) { $form = $a; } else { return strnatcmp($form[$a]['#title'], $form[$b]['#title']); } } /** * Try to guess the $type and $ids by looking at $_GET['q']. */ function _nodewords_detect_type_and_ids() { $arg = arg(); $bool = ( !variable_get('nodewords_list_repeat', FALSE) && isset($_REQUEST['page']) && intval($_REQUEST['page']) > 0 ); if ($bool) { return array(NODEWORDS_MT_TYPE_PAGER, array(0)); } if (variable_get('site_offline', 0) && !user_access('administer site configuration')) { return array('none', array()); } if (drupal_is_front_page() && variable_get('nodewords_use_frontpage_tags', TRUE)) { return array(NODEWORDS_MT_TYPE_FRONTPAGE, array(0)); } $headers = drupal_get_headers(); if (preg_match('@HTTP/1\.[01]\x20+403@', $headers)) { return array(NODEWORDS_MT_TYPE_ERRORPAGE, array(403)); } if (preg_match('@HTTP/1\.[01]\x20+404@', $headers)) { return array(NODEWORDS_MT_TYPE_ERRORPAGE, array(404)); } if (!isset($arg[0])) { return array('none', array()); } _nodewords_load_all_includes(); foreach (module_implements('nodewords_type_id') as $module) { $result = module_invoke($module, 'nodewords_type_id', $arg); if (isset($result) && is_array($result) && count($result) > 2) { return $result; } } foreach (_nodewords_get_pages_data() as $page) { if (preg_match($page->regexp, $_GET['q'])) { return array('page', array($page->path)); } } return array('none', array()); } /** * Load the page meta tags data from the cache. * * @param $id * The ID of the page to load; by default the function loads all the custom * pages data. */ function _nodewords_get_pages_data($id = NULL) { static $pages; if (!isset($pages)) { $pages = array(); $result = db_query("SELECT * FROM {nodewords_custom} ORDER BY weight ASC"); while ($page = db_fetch_object($result)) { $page->regexp = '/^('. preg_replace('/\\\\\*/', '.*', preg_quote($page->path, '/')) .')$/'; $page->tags = nodewords_load_tags('page', $page->path); $pages[$page->pid] = $page; } } return isset($id) ? (isset($pages[$id]) ? $pages[$id] : FALSE) : $pages; } function _nodewords_teaser_match_callback($matches, $init = FALSE) { static $bool; if ($init) { $bool = $matches; } if ($bool && !empty($matches[1])) { return ' ' . $matches[1] . ' '; } return ''; } /***************************************************************************** * Private functions. ****************************************************************************/ function _nodewords_load_all_includes() { $dir = drupal_get_path('module', 'nodewords') . '/includes'; foreach (file_scan_directory($dir, '.*\.inc', array('.', '..', 'CVS'), 0, FALSE) as $filename => $info) { if (module_exists($info->name)) { include_once './' . $filename; } } } /** * @} End of "addtogroup nodewords". */