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 = ( module_exists('vertical_tabs') && function_exists('vertical_tabs_add_vertical_tabs') && $form_id == 'nodewords_settings_form' ); if ($bool) { vertical_tabs_add_vertical_tabs($form); } $bool = ( isset($form['type']) && isset($form['type']['#value']) && $form_id == $form['type']['#value'] . '_node_form' && isset($form['#node']) && variable_get('nodewords_enable_node_metatags', TRUE) && variable_get('nodewords_edit_metatags_' . $form['type']['#value'], TRUE) ); if ($bool) { $node = $form['#node']; $form['nodewords'] = nodewords_form( NODEWORDS_TYPE_NODE, !empty($node->nodewords) ? $node->nodewords : array(), 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_TYPE_TERM, $id); } else { $tags = array(); } $form['nodewords'] = nodewords_form( NODEWORDS_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_TYPE_VOCABULARY, $id); } else { $tags = array(); } $form['nodewords'] = nodewords_form( NODEWORDS_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. The meta tags set in these page are used before the ones set for nodes or user profiles, and they can ovverride those meta tags.') . '

'; 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_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_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_TYPE_FRONTPAGE), '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_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_TYPE_NODE), ), ); return $operations; } /** * Implementation of hook_node_type(). */ function nodewords_node_type($op, $info) { if ($op == 'delete') { variable_del('nodewords_edit_metatags_' . $info->type); } } /** * Implementation of hook_nodeapi(). */ function nodewords_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) { switch ($op) { case 'delete': nodewords_delete_tags(NODEWORDS_TYPE_NODE, $node->nid); break; case 'insert': case 'update': if (isset($node->nodewords)) { nodewords_save_tags(NODEWORDS_TYPE_NODE, $node->nid, $node->nodewords, TRUE); } break; case 'load': return array( 'nodewords' => nodewords_load_tags(NODEWORDS_TYPE_NODE, $node->nid), ); case 'update index': $output_tags = array(); $tag_options = array( 'type' => NODEWORDS_TYPE_NODE, 'ids' => array($node->nid), 'output' => 'update index', ); if (isset($node->nodewords)) { // Prepare the tags. foreach (nodewords_get_possible_tags() as $name => $info) { $bool = ( !empty($info['tag:template:index']) && function_exists($function = $info['tag:function:prefix'] . '_prepare') ); if ($bool) { $tag_options['parameters'] = !empty($info['tag:function:parameters']) ? $info['tag:function:parameters'] : array(); $function( $output_tags, isset($node->nodewords[$name]) ? $node->nodewords[$name] : array(), $tag_options ); } } drupal_alter('nodewords_tags', $output_tags, $tag_options); $output = nodewords_output_tags($output_tags, 'update index'); drupal_alter('nodewords_tags_output', $output, $tag_options); return $output; } return ''; } } /** * Implementation of hook_perm(). */ function nodewords_perm() { return array('administer meta tags'); } /** * Implementation of hook_preprocess_page(). */ function nodewords_preprocess_page(&$variables) { $result = _nodewords_detect_type_and_ids(); $tags = nodewords_get_tags($result[0], $result[1]); $parameters = array( 'type' => $result[0], 'ids' => $result[1], 'output' => 'head', ); drupal_alter('nodewords_tags', $tags, $parameters); $output = nodewords_output_tags($tags); drupal_alter('nodewords_tags_output', $output, $parameters); drupal_set_html_head($output); $variables['head'] = drupal_get_html_head(); } /** * Implementation of hook_taxonomy(). */ function nodewords_taxonomy($op, $type, $object = NULL) { if ($type == NODEWORDS_TYPE_TERM) { $id = $object['tid']; } elseif ($type == NODEWORDS_TYPE_VOCABULARY) { $id = $object['vid']; } 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()), 'file' => 'nodewords.admin.inc', ), ); } /** * 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_TYPE_USER, $account->uid); } break; case 'delete': nodewords_delete_tags(NODEWORDS_TYPE_USER, $account->uid); break; case 'insert': case 'update': if (isset($edit['nodewords'])) { nodewords_save_tags(NODEWORDS_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_TYPE_USER, $account->uid); $form['nodewords'] = nodewords_form( NODEWORDS_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_TYPE_USER), ), ); return $operations; } /***************************************************************************** * Public functions. ****************************************************************************/ /** * Delete tags from table. */ function nodewords_delete_tags($type, $id) { db_query("DELETE FROM {nodewords} WHERE type = '%s' AND id = '%s'", $type, $id); if ($type == NODEWORDS_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(); $head_tags = variable_get('nodewords_head', array()); $options += $default_options; $tag_options = array( 'default' => nodewords_load_tags(), 'type' => $type, ); if (isset($options['tag_options'])) { $tag_options = array_merge($options['tag_options'], $tag_options); } $tags_info = nodewords_get_possible_tags(); foreach ($tags_info as $name => $info) { if ($type != NODEWORDS_TYPE_DEFAULT && empty($edit_tags[$name])) { continue; } $bool = ( ( !empty($info['tag:context:allowed']) && is_array($info['tag:context:allowed']) && !in_array($type, $info['tag:context:allowed']) ) || ( !empty($info['tag:context:denied']) && is_array($info['tag:context:denied']) && in_array($type, $info['tag:context:denied']) ) ); if ($bool) { 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) && $options['fieldset']) { $form['#type'] = 'fieldset'; $form['#title'] = $options['fieldset:title']; $form['#tree'] = TRUE; $form['#collapsible'] = TRUE; $form['#collapsed'] = TRUE; $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'); $version = 0; if (isset($result)) { if (is_numeric($result)) { $version = $result; } elseif (is_array($result) && isset($result['version'])) { $version = $result['version']; } } $bool = ( version_compare($version, NODEWORDS_MINIMUM_API_VERSION, '<') || version_compare($version, NODEWORDS_API_VERSION, '>') ); if ($bool) { 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_TYPE_ERRORPAGE, NODEWORDS_TYPE_FRONTPAGE, NODEWORDS_TYPE_NODE, * NODEWORDS_TYPE_PAGE, NODEWORDS_TYPE_TERM, NODEWORDS_TYPE_TRACKER, NODEWORDS_TYPE_VOCABULARY. * @param $ids * ID of the object to get the meta tags from. * This is one of the following: * - NODEWORDS_TYPE_ERRORPAGE => an array containing the HTML error code (403 or 404). * - NODEWORDS_TYPE_FRONTPAGE => none. * - NODEWORDS_TYPE_NODE => an array containing the node ID. * - NODEWORDS_TYPE_PAGE => an array containing the page path. * - NODEWORDS_TYPE_TERM => an array of term IDs. * - NODEWORDS_TYPE_USER => an array containing the user ID. * - NODEWORDS_TYPE_VOCABULARY => an array of vocabulary IDs. * @param $options * An array of additional options. Currently the only defined is 'filter', * which filter the list of meta tags to the enabled ones. * * @return * An associative array of the defined meta tags. */ function nodewords_get_tags($type, $ids = array(''), $options = array()) { $default_options = array( 'filter' => TRUE, ); $head_tags = variable_get('nodewords_head', array()); $options += $default_options; $output_tags = array(); if (!is_array($ids)) { $ids = array($ids); } $tag_options = array( 'default' => nodewords_load_tags(), 'type' => $type, 'ids' => $ids, ); if ($type == NODEWORDS_TYPE_PAGER) { foreach (nodewords_get_possible_tags() as $name => $info) { // Filter out tags the user has chosen not to see if ($options['filter'] && empty($head_tags[$name])) { continue; } $bool = ( !empty($info['tag:context:allowed']) && in_array(NODEWORDS_TYPE_PAGER, $info['tag:context:allowed']) && function_exists($function = $info['tag:function:prefix'] . '_prepare') ); if ($bool) { $tag_options['parameters'] = !empty($info['tag:function:parameters']) ? $info['tag:function:parameters'] : array(); $function($output_tags, array(), $tag_options); } } } else { // User profiles meta tags are not enabled. if ($type == NODEWORDS_TYPE_USER && !variable_get('nodewords_enable_user_metatags', TRUE)) { return array(); } // Load the values from the database elseif (count($ids) == 1 && ($type != NODEWORDS_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) { // Filter out tags the user has chosen not to see if ($options['filter'] && empty($head_tags[$name])) { continue; } 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); } } } 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_TYPE_DEFAULT, $id = '') { $result = db_query("SELECT * FROM {nodewords} WHERE type = '%s' 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_TYPE_TERM) { return nodewords_load_tags(NODEWORDS_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_TYPE_NODE, NODEWORDS_TYPE_USER, * NODEWORDS_TYPE_PAGER, NODEWORDS_TYPE_PAGE, ...). */ function nodewords_mass_delete_tags($ids, $type) { db_query("DELETE FROM {nodewords} WHERE id IN (" . db_placeholders($ids, 'varchar') . ") AND type = '%s'", array_merge($ids, array($type)) ); if ($type == NODEWORDS_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 $text * The string to use. * @param $format * The format set for the node. * @param $options * An array of options; currently, the only used is the maximum allowed * length. * * @return * The string to use to populate the meta tag. */ function nodewords_metatag_from_teaser($text, $format, $options = array()) { $default_options = array( 'size' => variable_get('nodewords_max_size', 350), ); $options += $default_options; // 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($text, ']*alt=["\']([^"\']*)["\'][^>]*>/i', '_nodewords_teaser_match_callback', $text ) ); // Remove the strings added from third-party modules. $modules = array_filter(variable_get('nodewords_filter_modules_output', array())); if (isset($modules['imagebrowser'])) { $text = preg_replace('/\[ibimage[^[\]*\]/i', '', $text); } if (isset($modules['img_assist'])) { $text = preg_replace('/\[img_assist[^[\]*\]/i', '', $text); } // Remove the text matching the regular expression. if ($regexp = trim(variable_get('nodewords_filter_regexp', ''))) { $text = preg_replace('/' . $regexp . '/i', '', $text); } // Truncate the string at last space within the given size. return truncate_utf8($text, $options['size'], TRUE); } /** * Render the meta tag values as HTML. * * @param $tags * An array of tags (as returned by nodewords_get_tags()). * * @param $output_type * The type of output, 'head' (default), or 'update index'. * * @return * A string containing the HTML output for the META tag. */ function nodewords_output_tags($tags, $output_type = 'head') { $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]; } if ($output_type == 'update index') { $bool = ( isset($tags_info[$parts[0]]['tag:template:index'][$parts[1]]) && ($meta_content = trim(check_plain(strip_tags(decode_entities($content))))) ); if ($bool) { $replace = array( '%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:index'][$parts[1]]; $weight = isset($tags_info[$parts[0]]['tag:weight'][$parts[1]]) ? $tags_info[$parts[0]]['tag:weight'][$parts[1]] : 0; } } else { $bool = ( isset($tags_info[$parts[0]]['tag:template'][$parts[1]]) && ($meta_name = check_plain(strip_tags(decode_entities($parts[1])))) && ($meta_content = trim(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; } } if (count($output)) { array_multisort($weights, $output); return implode("\n", $output); } else { return ''; } } /** * 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); } /** * 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 = '%s' 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' : array()); if (!$done) { watchdog('nodewords', 'User %name changed the meta tags for type %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. ****************************************************************************/ /** * Try to guess the $type and $ids by looking at $_GET['q']. */ function _nodewords_detect_type_and_ids() { $arg = arg(); if (variable_get('site_offline', 0) && !user_access('administer site configuration')) { return array(NODEWORDS_TYPE_NONE, array()); } $headers = drupal_get_headers(); if (preg_match('@HTTP/1\.[01]\x20+403@', $headers)) { return array(NODEWORDS_TYPE_ERRORPAGE, 403); } if (preg_match('@HTTP/1\.[01]\x20+404@', $headers)) { return array(NODEWORDS_TYPE_ERRORPAGE, 404); } $bool = ( !variable_get('nodewords_list_repeat', FALSE) && isset($_REQUEST['page']) && intval($_REQUEST['page']) > 0 ); if ($bool) { return array(NODEWORDS_TYPE_PAGER, 0); } if (drupal_is_front_page() && variable_get('nodewords_use_frontpage_tags', TRUE)) { return array(NODEWORDS_TYPE_FRONTPAGE, ''); } foreach (_nodewords_get_pages_data() as $page) { $path = $page->path; if (drupal_match_path($_GET['q'], $path)) { return array(NODEWORDS_TYPE_PAGE, $path); } $bool = ( ($alias = drupal_get_path_alias($_GET['q'])) != $_GET['q'] && drupal_match_path($alias, $path) ); if ($bool) { return array(NODEWORDS_TYPE_PAGE, $path); } } if (!isset($arg[0])) { return array(NODEWORDS_TYPE_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; } } return array(NODEWORDS_TYPE_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->tags = nodewords_load_tags(NODEWORDS_TYPE_PAGE, $page->path); $pages[$page->pid] = $page; } } return isset($id) ? (isset($pages[$id]) ? $pages[$id] : FALSE) : $pages; } /** * Load the files in the directory "includes" basing on the modules enabled. * */ 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)) { module_load_include('inc', 'nodewords', 'includes/' . $info->name); } } } /** * Helper function for preg_match_callback(), called when replacing the tag img * in the teaser, when using it as meta tag DESCRIPTION content. */ function _nodewords_teaser_match_callback($matches) { static $bool; if (!isset($bool)) { $bool = variable_get('nodewords_use_alt_attribute', FALSE); } if ($bool && !empty($matches[1])) { return ' ' . $matches[1] . ' '; } return ''; } /** * @} End of "addtogroup nodewords". */