| 1 |
|
<?php |
| 2 |
|
// $Id$ |
| 3 |
|
|
| 4 |
|
/** |
| 5 |
|
* @file Provides an add-on to the Meta Tag (nodewords) module to allow |
| 6 |
|
* per-path meta tag values. |
| 7 |
|
*/ |
| 8 |
|
|
| 9 |
|
/** The empty field specifier. */ |
| 10 |
|
define('NODEWORDS_NONE', '<none>'); |
| 11 |
|
|
| 12 |
|
require_once(drupal_get_path('module', 'nodewords_bypath') . '/nodewords_bypath.forms.inc'); |
| 13 |
|
|
| 14 |
|
|
| 15 |
|
/** |
| 16 |
|
* Implementation of hook_help(). |
| 17 |
|
* |
| 18 |
|
* @param $section string A path indicating which help text to display. |
| 19 |
|
* |
| 20 |
|
* @return string The help text for the provided path. |
| 21 |
|
*/ |
| 22 |
|
function nodewords_bypath_help($section) { |
| 23 |
|
switch($section) { |
| 24 |
|
case 'admin/content/nodewords/path': |
| 25 |
|
$subs = array('!ref_link' => l(t('Token Reference Page'), 'admin/content/nodewords/path/tokens')); |
| 26 |
|
$help = '<p>' . t('Meta tag path rules allow the values of meta tags to be specified by path. The value may include dynamic content using the tokens specified in the !ref_link page. Rules are evaluated by their weight with lighter rules are evaluated before heavier ones. Rule evaluation stops on the first rule encountered that matches any given path. For example, if the lightest weight rule matches a path, that rule is evaluated and no further rules are evaluated against that path.', $subs) . '</p>'; |
| 27 |
|
return $help; |
| 28 |
|
|
| 29 |
|
case 'admin/content/nodewords/path/new': |
| 30 |
|
// Fall through. |
| 31 |
|
case 'admin/content/nodewords/path/edit/' . arg(5): |
| 32 |
|
$help = '<p>' . t('When using tokens in the meta tag fields, keep in mind that node tokens are only available when a page is displaying a single node. Global tokens are available on all pages.') . '</p>'; |
| 33 |
|
return $help; |
| 34 |
|
} |
| 35 |
|
} |
| 36 |
|
|
| 37 |
|
|
| 38 |
|
/** |
| 39 |
|
* Implementation of hook_menu(). |
| 40 |
|
* |
| 41 |
|
* @param $may_cache bool TRUE if this call is for the cached menu, |
| 42 |
|
* FALSE if not. |
| 43 |
|
*/ |
| 44 |
|
function nodewords_bypath_menu($may_cache) { |
| 45 |
|
$items = array(); |
| 46 |
|
|
| 47 |
|
if ($may_cache) { |
| 48 |
|
$items[] = array( |
| 49 |
|
'path' => 'admin/content/nodewords/path', |
| 50 |
|
'title' => t('By Path'), |
| 51 |
|
'callback' => 'drupal_get_form', |
| 52 |
|
'callback arguments' => array('nodewords_bypath_admin_overview'), |
| 53 |
|
'type' => MENU_LOCAL_TASK, |
| 54 |
|
'access' => user_access('administer meta tags'), |
| 55 |
|
'weight' => 5, |
| 56 |
|
); |
| 57 |
|
|
| 58 |
|
$items[] = array( |
| 59 |
|
'path' => 'admin/content/nodewords/path/list', |
| 60 |
|
'title' => t('List'), |
| 61 |
|
'callback' => 'nodewords_bypath_admin_overview', |
| 62 |
|
'type' => MENU_DEFAULT_LOCAL_TASK, |
| 63 |
|
'access' => user_access('administer meta tags'), |
| 64 |
|
); |
| 65 |
|
|
| 66 |
|
$items[] = array( |
| 67 |
|
'path' => 'admin/content/nodewords/path/new', |
| 68 |
|
'title' => t('New Rule'), |
| 69 |
|
'callback' => 'drupal_get_form', |
| 70 |
|
'callback arguments' => array('nodewords_bypath_create_form'), |
| 71 |
|
'type' => MENU_LOCAL_TASK, |
| 72 |
|
'weight' => 1, |
| 73 |
|
'access' => user_access('administer meta tags'), |
| 74 |
|
); |
| 75 |
|
|
| 76 |
|
if (function_exists('token_get_list')) { |
| 77 |
|
$items[] = array( |
| 78 |
|
'path' => 'admin/content/nodewords/path/tokens', |
| 79 |
|
'title' => t('Token Reference'), |
| 80 |
|
'callback' => 'drupal_get_form', |
| 81 |
|
'callback arguments' => array('nodewords_bypath_tokenref_form'), |
| 82 |
|
'type' => MENU_LOCAL_TASK, |
| 83 |
|
'weight' => 2, |
| 84 |
|
'access' => user_access('administer meta tags'), |
| 85 |
|
); |
| 86 |
|
} |
| 87 |
|
} |
| 88 |
|
else { |
| 89 |
|
$items[] = array( |
| 90 |
|
'path' => 'admin/content/nodewords/path/edit/' . arg(5), |
| 91 |
|
'callback' => 'drupal_get_form', |
| 92 |
|
'callback arguments' => array('nodewords_bypath_create_form', arg(5)), |
| 93 |
|
'type' => MENU_CALLBACK, |
| 94 |
|
'access' => user_access('administer meta tags'), |
| 95 |
|
); |
| 96 |
|
|
| 97 |
|
$items[] = array( |
| 98 |
|
'path' => 'admin/content/nodewords/path/delete/' . arg(5), |
| 99 |
|
'callback' => 'drupal_get_form', |
| 100 |
|
'callback arguments' => array('nodewords_bypath_delete_form', arg(5)), |
| 101 |
|
'type' => MENU_CALLBACK, |
| 102 |
|
'access' => user_access('administer meta tags'), |
| 103 |
|
); |
| 104 |
|
} |
| 105 |
|
|
| 106 |
|
return $items; |
| 107 |
|
} |
| 108 |
|
|
| 109 |
|
|
| 110 |
|
/** |
| 111 |
|
* Implementation of hook_nodewords(). |
| 112 |
|
* |
| 113 |
|
* @param &$tags array The meta-tag => value pairs that will be written to |
| 114 |
|
* the document head. |
| 115 |
|
* @param $op string The operation being performed. This implementation only |
| 116 |
|
* responds to 'prepare'. |
| 117 |
|
* @param $type string The type being viewed ('node' or 'term', all others |
| 118 |
|
* treated as 'global'). |
| 119 |
|
* @param $ids array The node ID (single element array) if type 'node', or |
| 120 |
|
* an array of term IDs if type 'term'. |
| 121 |
|
*/ |
| 122 |
|
function nodewords_bypath_nodewords(&$tags, $op, $type, $ids) { |
| 123 |
|
switch ($op) { |
| 124 |
|
case 'prepare': |
| 125 |
|
$path = drupal_get_path_alias($_GET['q']); |
| 126 |
|
$rule = _nodewords_bypath_get_path_rule($path); |
| 127 |
|
$rule_tags = _nodewords_bypath_get_tags_for($rule->id); |
| 128 |
|
|
| 129 |
|
//-------------------------------------------------------------------- |
| 130 |
|
// Determine the context for token replacement. |
| 131 |
|
$scope = 'global'; |
| 132 |
|
$object = NULL; |
| 133 |
|
|
| 134 |
|
if ($type == 'node') { |
| 135 |
|
$scope = 'node'; |
| 136 |
|
$object = node_load($ids[0]); |
| 137 |
|
} |
| 138 |
|
else if ($type == 'term') { |
| 139 |
|
$scope = 'taxonomy'; |
| 140 |
|
$object = taxonomy_get_term($ids[0]); |
| 141 |
|
} |
| 142 |
|
|
| 143 |
|
//-------------------------------------------------------------------- |
| 144 |
|
// Set the value for the tag and use the token module if it is |
| 145 |
|
// available. |
| 146 |
|
foreach ($rule_tags as $key => $value) { |
| 147 |
|
if (!empty($value)) { |
| 148 |
|
if (function_exists('token_replace')) { |
| 149 |
|
$tags[$key] = strip_tags(token_replace($value, $scope, $object)); |
| 150 |
|
} |
| 151 |
|
else { |
| 152 |
|
$tags[$key] = $value; |
| 153 |
|
} |
| 154 |
|
} |
| 155 |
|
elseif ($value == NODEWORDS_NONE) { |
| 156 |
|
$tags[$key] = ''; |
| 157 |
|
} |
| 158 |
|
} |
| 159 |
|
|
| 160 |
|
break; |
| 161 |
|
} |
| 162 |
|
} |
| 163 |
|
|
| 164 |
|
|
| 165 |
|
/** |
| 166 |
|
* Persist a rule instance to the database |
| 167 |
|
* |
| 168 |
|
* @param $rule object The rule instance to create or update. |
| 169 |
|
*/ |
| 170 |
|
function _nodewords_bypath_save($rule) { |
| 171 |
|
// Updating an existing rule |
| 172 |
|
if (isset($rule->id) && ($rule->id > -1)) { |
| 173 |
|
db_query("UPDATE {nodewords_bypath_rules} SET |
| 174 |
|
name = '%s', type = %d, path_expr = '%s', weight = %d |
| 175 |
|
WHERE id = %d", |
| 176 |
|
$rule->name, $rule->type, $rule->path_expr, |
| 177 |
|
$rule->weight, $rule->id); |
| 178 |
|
|
| 179 |
|
//---------------------------------------------------------------------- |
| 180 |
|
// Tags are trickier. They could exist already, or they may be new if |
| 181 |
|
// the administrator has recently changed the available tags. |
| 182 |
|
foreach ($rule->tags as $tag => $value) { |
| 183 |
|
$exists = db_result(db_query("SELECT COUNT(*) FROM {nodewords_bypath_tags} |
| 184 |
|
WHERE (rule_id = %d AND meta_tag = '%s')", |
| 185 |
|
$rule->id, $tag)); |
| 186 |
|
if ($exists > 0) { |
| 187 |
|
db_query("UPDATE {nodewords_bypath_tags} SET meta_value = '%s' |
| 188 |
|
WHERE (rule_id = %d AND meta_tag = '%s')", |
| 189 |
|
$value, $rule->id, $tag); |
| 190 |
|
} |
| 191 |
|
else { |
| 192 |
|
db_query("INSERT INTO {nodewords_bypath_tags} (rule_id, meta_tag, meta_value) |
| 193 |
|
VALUES (%d, '%s', '%s')", $rule->id, $tag, $value); |
| 194 |
|
} |
| 195 |
|
} |
| 196 |
|
} |
| 197 |
|
// Saving a new rule |
| 198 |
|
else { |
| 199 |
|
$id = db_next_id('{nodewords_bypath_rules}_id'); |
| 200 |
|
db_query("INSERT INTO {nodewords_bypath_rules} |
| 201 |
|
(id, name, type, path_expr, weight) |
| 202 |
|
VALUES (%d, '%s', %d, '%s', %d)", |
| 203 |
|
$id, $rule->name, $rule->type, |
| 204 |
|
$rule->path_expr, $rule->weight); |
| 205 |
|
foreach ($rule->tags as $tag => $value) { |
| 206 |
|
db_query("INSERT INTO {nodewords_bypath_tags} (rule_id, meta_tag, meta_value) |
| 207 |
|
VALUES (%d, '%s', '%s')", $id, $tag, $value); |
| 208 |
|
} |
| 209 |
|
} |
| 210 |
|
} |
| 211 |
|
|
| 212 |
|
|
| 213 |
|
/** |
| 214 |
|
* Retrieve the meta tags for the given rule ID. |
| 215 |
|
* |
| 216 |
|
* @param $id int The rule to get the terms for. |
| 217 |
|
* |
| 218 |
|
* @return array A mapping of term names (string) to their values (string). |
| 219 |
|
*/ |
| 220 |
|
function _nodewords_bypath_get_tags_for($id) { |
| 221 |
|
$tags = array(); |
| 222 |
|
$result = db_query('SELECT meta_tag, meta_value |
| 223 |
|
FROM {nodewords_bypath_tags} WHERE rule_id = %d', $id); |
| 224 |
|
while ($row = db_fetch_object($result)) { |
| 225 |
|
$tags[$row->meta_tag] = $row->meta_value; |
| 226 |
|
} |
| 227 |
|
|
| 228 |
|
return $tags; |
| 229 |
|
} |
| 230 |
|
|
| 231 |
|
|
| 232 |
|
/** |
| 233 |
|
* Load a meta tag rule by its ID. |
| 234 |
|
* |
| 235 |
|
* @param $id int The unique ID of the meta rule to load. |
| 236 |
|
* |
| 237 |
|
* @return array The meta tag rule information, or NULL if no rule with the |
| 238 |
|
* given ID was found. |
| 239 |
|
*/ |
| 240 |
|
function _nodewords_bypath_load_instance($id) { |
| 241 |
|
$title = NULL; |
| 242 |
|
|
| 243 |
|
$result = db_fetch_object(db_query('SELECT id, name, type, path_expr, weight |
| 244 |
|
FROM {nodewords_bypath_rules} WHERE id = %d', $id)); |
| 245 |
|
|
| 246 |
|
if (!empty($result) AND (!empty($result->id))) { |
| 247 |
|
$result->tags = _nodewords_bypath_get_tags_for($result->id); |
| 248 |
|
} |
| 249 |
|
|
| 250 |
|
return $result; |
| 251 |
|
} |
| 252 |
|
|
| 253 |
|
|
| 254 |
|
/** |
| 255 |
|
* Retrieve all the meta tag rules. |
| 256 |
|
* |
| 257 |
|
* @return array The meta tag rule objects. |
| 258 |
|
*/ |
| 259 |
|
function _nodewords_bypath_get_all() { |
| 260 |
|
$rules = array(); |
| 261 |
|
$result = db_query('SELECT id, name, type, path_expr, weight |
| 262 |
|
FROM {nodewords_bypath_rules} ORDER BY weight, name ASC'); |
| 263 |
|
|
| 264 |
|
// The tags aren't loaded here. They're loaded on demand when the path |
| 265 |
|
// is matched. |
| 266 |
|
while ($row = db_fetch_object($result)) { |
| 267 |
|
$rules[] = $row; |
| 268 |
|
} |
| 269 |
|
|
| 270 |
|
return $rules; |
| 271 |
|
} |
| 272 |
|
|
| 273 |
|
|
| 274 |
|
/** |
| 275 |
|
* Retrieve the meta tag rule for the given path. |
| 276 |
|
* |
| 277 |
|
* @param $path string The Drupal path to replace the title for. |
| 278 |
|
* |
| 279 |
|
* @return object The meta tag rule for the given path. |
| 280 |
|
*/ |
| 281 |
|
function _nodewords_bypath_get_path_rule($path) { |
| 282 |
|
$rules = _nodewords_bypath_get_all(); |
| 283 |
|
|
| 284 |
|
foreach ($rules as $rule) { |
| 285 |
|
//---------------------------------------------------------------------- |
| 286 |
|
// Rules are processed lightest first, so if this tag has already been |
| 287 |
|
// added for this path, this rule is skipped. |
| 288 |
|
if ($rule->type == 1) { |
| 289 |
|
$regexp = '/^('. |
| 290 |
|
preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\<front\\\\>($|\|)/'), |
| 291 |
|
array('|', '.*', '\1'. preg_quote(variable_get('site_frontpage', 'node'), '/') .'\2'), |
| 292 |
|
preg_quote($rule->path_expr, '/')) . |
| 293 |
|
')$/'; |
| 294 |
|
|
| 295 |
|
// Compare with the Drupal path and the query. |
| 296 |
|
$page_match = preg_match($regexp, $path); |
| 297 |
|
if ($path != $_GET['q']) { |
| 298 |
|
$page_match = $page_match || preg_match($regexp, $_GET['q']); |
| 299 |
|
} |
| 300 |
|
} |
| 301 |
|
elseif ($rule->type == 2) { |
| 302 |
|
$page_match = drupal_eval($rule->path_expr); |
| 303 |
|
} |
| 304 |
|
|
| 305 |
|
if ($page_match > 0) { |
| 306 |
|
return $rule; |
| 307 |
|
} |
| 308 |
|
} |
| 309 |
|
|
| 310 |
|
return NULL; |
| 311 |
|
} |