path_redirect.module

Tracking 6.x-1.x branch
  1. drupal
    1. 5 contributions/path_redirect/path_redirect.module
    2. 6 contributions/path_redirect/path_redirect.module
    3. 7 contributions/path_redirect/path_redirect.module

Functions & methods

NameDescription
path_redirect_build_url
path_redirect_check_alias_changedCreates a redirect if an URL alias is being changed.
path_redirect_clear_cache
path_redirect_compare_arrayCompare tha all values and associations in one array match another array.
path_redirect_content_extra_fieldsImplements hook_content_extra_fields().
path_redirect_cronImplements hook_cron().
path_redirect_deleteDelete a redirect.
path_redirect_delete_multipleDelete multiple redirects.
path_redirect_form_alterImplements hook_form_alter().
path_redirect_get_path
path_redirect_get_query
path_redirect_get_query_arraySplit an URL-encoded query string into an array.
path_redirect_goto
path_redirect_helpImplements hook_help().
path_redirect_initImplements hook_init().
path_redirect_loadLoad a redirect by ID.
path_redirect_load_by_sourceLoad a redirect by incoming path and language.
path_redirect_load_multiple
path_redirect_local_actions
path_redirect_menuImplements hook_menu().
path_redirect_nodeapiImplements hook_nodeapi().
path_redirect_path_redirect_operationsImplements hook_path_redirect_operations().
path_redirect_permImplements hook_perm().
path_redirect_saveSave an URL redirect to the database.
path_redirect_taxonomyImplements hook_taxonomy().
path_redirect_userImplements hook_user().
path_redirect_variables
_path_redirect_build_conditions
_path_redirect_uasortuasort callback; Compare redirects based on language neutrality and rids.

File

View source
  1. <?php
  2. /**
  3. * Implements hook_help().
  4. */
  5. function path_redirect_help($path, $arg) {
  6. $output = '';
  7. switch ($path) {
  8. case 'admin/build/path-redirect':
  9. case 'admin/build/path-redirect/list':
  10. //$output .= '<p>' . t('Here you can set up URL redirecting for this site. Any existing or non-existing path within this site can redirect to any internal or external URL.') .'</p>';
  11. break;
  12. case 'admin/build/path-redirect/add':
  13. case 'admin/build/path-redirect/edit/%':
  14. $output .= '<p>' . t('If you need advanced redirection functionality (i.e. wildcards, etc.), you should be using a <a href="http://en.wikipedia.org/wiki/Mod_rewrite">webserver rewriting engine</a> rather than this module.') . '</p>';
  15. break;
  16. }
  17. return $output;
  18. }
  19. /**
  20. * Implements hook_perm().
  21. */
  22. function path_redirect_perm() {
  23. return array(
  24. 'administer redirects',
  25. );
  26. }
  27. /**
  28. * Implements hook_menu().
  29. */
  30. function path_redirect_menu() {
  31. $items['admin/build/path-redirect'] = array(
  32. 'title' => 'URL redirects',
  33. 'description' => 'Redirect users from one URL to another.',
  34. 'page callback' => 'drupal_get_form',
  35. 'page arguments' => array('path_redirect_admin_redirects'),
  36. 'access arguments' => array('administer redirects'),
  37. 'file' => 'path_redirect.admin.inc',
  38. );
  39. $items['admin/build/path-redirect/list'] = array(
  40. 'title' => 'List',
  41. 'type' => MENU_DEFAULT_LOCAL_TASK,
  42. 'weight' => -10,
  43. );
  44. $items['admin/build/path-redirect/add'] = array(
  45. 'title' => 'Add redirect',
  46. 'description' => 'Add a new URL redirect.',
  47. 'page callback' => 'drupal_get_form',
  48. 'page arguments' => array('path_redirect_edit_form'),
  49. 'access arguments' => array('administer redirects'),
  50. 'type' => MENU_LOCAL_TASK,
  51. 'file' => 'path_redirect.admin.inc',
  52. );
  53. $items['admin/build/path-redirect/edit/%path_redirect'] = array(
  54. 'title' => 'Edit redirect',
  55. 'description' => 'Edit an existing URL redirect.',
  56. 'page callback' => 'drupal_get_form',
  57. 'page arguments' => array('path_redirect_edit_form', 4),
  58. 'access arguments' => array('administer redirects'),
  59. 'type' => MENU_CALLBACK,
  60. 'file' => 'path_redirect.admin.inc',
  61. );
  62. $items['admin/build/path-redirect/delete/%path_redirect'] = array(
  63. 'title' => 'Delete redirect',
  64. 'description' => 'Delete an existing URL redirect.',
  65. 'page callback' => 'drupal_get_form',
  66. 'page arguments' => array('path_redirect_delete_form', 4),
  67. 'access arguments' => array('administer redirects'),
  68. 'type' => MENU_CALLBACK,
  69. 'file' => 'path_redirect.admin.inc',
  70. );
  71. $items['admin/build/path-redirect/settings'] = array(
  72. 'title' => 'Settings',
  73. 'description' => 'Configure behavior for URL redirects.',
  74. 'page callback' => 'drupal_get_form',
  75. 'page arguments' => array('path_redirect_settings_form'),
  76. 'access arguments' => array('administer redirects'),
  77. 'type' => MENU_LOCAL_TASK,
  78. 'weight' => 10,
  79. 'file' => 'path_redirect.admin.inc',
  80. );
  81. $items['js/path_redirect/autocomplete_404'] = array(
  82. 'page callback' => 'path_redirect_js_autocomplete_404',
  83. 'access arguments' => array('administer redirects'),
  84. 'type' => MENU_CALLBACK,
  85. 'file' => 'path_redirect.admin.inc',
  86. );
  87. return $items;
  88. }
  89. /**
  90. * Implements hook_init().
  91. */
  92. function path_redirect_init() {
  93. if (defined('MAINTENANCE_MODE')) {
  94. return;
  95. }
  96. path_redirect_goto();
  97. }
  98. function path_redirect_goto($redirect = NULL) {
  99. if (!isset($redirect)) {
  100. $path = path_redirect_get_path();
  101. $language = $GLOBALS['language']->language;
  102. $query = path_redirect_get_query();
  103. $redirect = path_redirect_load_by_source($path, $language, $query);
  104. }
  105. elseif (is_numeric($redirect)) {
  106. $redirect = path_redirect_load($redirect);
  107. }
  108. if ($redirect) {
  109. // Create the absolute redirection URL.
  110. $redirect['redirect_url'] = url($redirect['redirect'], array('query' => $redirect['query'], 'fragment' => $redirect['fragment'], 'absolute' => TRUE));
  111. // Update the last used timestamp so that unused redirects can be purged.
  112. db_query("UPDATE {path_redirect} SET last_used = %d WHERE rid = %d", time(), $redirect['rid']);
  113. if (url($redirect['redirect']) == url($_GET['q'])) {
  114. // Prevent infinite loop redirection.
  115. watchdog('path_redirect', 'Redirect to <code>%redirect</code> is causing an infinite loop; redirect cancelled.', array('%redirect' => $redirect['redirect_url']), WATCHDOG_WARNING, l(t('Edit'), 'admin/build/path-redirect/edit/'. $redirect['rid']));
  116. }
  117. elseif (variable_get('path_redirect_allow_bypass', 0) && isset($_GET['redirect']) && $_GET['redirect'] === 'no') {
  118. // If the user has requested not to be redirected, show a message.
  119. drupal_set_message(t('This page has been moved to <a href="@redirect">@redirect</a>.', array('@redirect' => $redirect['redirect_url'])));
  120. }
  121. elseif (variable_get('path_redirect_redirect_warning', 0)) {
  122. // Show a message and automatically redirect after 10 seconds.
  123. drupal_set_message(t('This page has been moved to <a href="@redirect">@redirect</a>. You will be automatically redirected in 10 seconds.', array('@redirect' => $redirect['redirect_url'])), 'error');
  124. drupal_set_html_head('<meta http-equiv="refresh" content="10;url=' . $redirect['redirect_url'] . '" />');
  125. }
  126. else {
  127. // Perform the redirect.
  128. unset($_REQUEST['destination']);
  129. drupal_goto($redirect['redirect_url'], NULL, NULL, $redirect['type']);
  130. }
  131. }
  132. // If this is being executed as a menu item, return a not found flag.
  133. return MENU_NOT_FOUND;
  134. }
  135. /**
  136. * Implements hook_cron().
  137. */
  138. function path_redirect_cron() {
  139. // Purge inactive redirects from the database.
  140. if ($purge = variable_get('path_redirect_purge_inactive', 0)) {
  141. $query = db_query("SELECT rid FROM {path_redirect} WHERE last_used < %d", time() - $purge);
  142. $rids = array();
  143. while ($rid = db_result($query)) {
  144. $rids[] = $rid;
  145. }
  146. if ($rids) {
  147. path_redirect_delete_multiple($rids);
  148. watchdog('path_redirect', format_plural(count($rids), 'Removed 1 inactive redirect from the database.', 'Removed @count inactive redirects from the database.'));
  149. }
  150. }
  151. }
  152. /**
  153. * Implements hook_path_redirect_operations().
  154. */
  155. function path_redirect_path_redirect_operations() {
  156. $operations = array(
  157. 'delete' => array(
  158. 'action' => t('Delete'),
  159. 'action_past' => t('Deleted'),
  160. 'callback' => 'path_redirect_delete_multiple',
  161. 'confirm' => TRUE,
  162. ),
  163. );
  164. return $operations;
  165. }
  166. /**
  167. * Implements hook_content_extra_fields().
  168. *
  169. * This is so that the URL redirect fieldset is sortable on the node edit form.
  170. */
  171. function path_redirect_content_extra_fields() {
  172. $extras['path_redirect'] = array(
  173. 'label' => t('URL redirects'),
  174. 'description' => t('Path redirect module listing'),
  175. 'weight' => 30,
  176. );
  177. return $extras;
  178. }
  179. /**
  180. * Implements hook_form_alter().
  181. *
  182. * Add a summary of redirects pointing to a node on its edit form.
  183. */
  184. function path_redirect_form_alter(&$form, $form_state, $form_id) {
  185. if (substr($form_id, -10) == '_node_form' && !empty($form['#node']->nid)) {
  186. $redirect = array(
  187. 'redirect' => 'node/' . $form['#node']->nid,
  188. 'language' => $form['#node']->language,
  189. );
  190. $form['path_redirect'] = array(
  191. '#type' => 'fieldset',
  192. '#title' => t('URL redirects'),
  193. '#description' => t('The following are a list of URL redirects that point to this location.'),
  194. '#collapsible' => TRUE,
  195. '#collapsed' => TRUE,
  196. '#access' => user_access('administer redirects'),
  197. '#weight' => 30,
  198. '#group' => 'additional_settings',
  199. '#attached' => array(
  200. 'js' => array(
  201. 'vertical-tabs' => drupal_get_path('module', 'path_redirect') . '/path_redirect.js',
  202. ),
  203. ),
  204. );
  205. module_load_include('inc', 'path_redirect', 'path_redirect.admin');
  206. $form['path_redirect']['table'] = path_redirect_list_redirects(array(), array('redirect' => 'node/' . $form['#node']->nid));
  207. $form['path_redirect']['add'] = array(
  208. '#value' => path_redirect_local_actions($redirect),
  209. );
  210. }
  211. }
  212. function path_redirect_local_actions($redirect = array()) {
  213. $links = array(
  214. 'add' => array(
  215. 'title' => $redirect ? t('Add redirect to this location') : t('Add redirect'),
  216. 'href' => 'admin/build/path-redirect/add',
  217. 'query' => drupal_get_destination() . ($redirect ? '&' . drupal_query_string_encode($redirect) : ''),
  218. ),
  219. );
  220. return theme('links', $links, array('class' => 'item-list action-links'));
  221. }
  222. /**
  223. * Implements hook_nodeapi().
  224. */
  225. function path_redirect_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  226. switch ($op) {
  227. case 'presave':
  228. if (!empty($node->nid) && !empty($node->path)) {
  229. path_redirect_check_alias_changed('node/' . $node->nid, $node->path, $node->language);
  230. }
  231. break;
  232. case 'delete':
  233. // When a node is deleted, also delete the redirects to it (they will result in a 404).
  234. path_redirect_delete_multiple(NULL, array('source' => 'node/'. $node->nid));
  235. path_redirect_delete_multiple(NULL, array('redirect' => 'node/'. $node->nid));
  236. break;
  237. }
  238. }
  239. /**
  240. * Creates a redirect if an URL alias is being changed.
  241. *
  242. * @param $path
  243. * The base (normal) path.
  244. * @param $new_alias
  245. * The new alias for the path.
  246. * @param $language
  247. * The language of the alias being created.
  248. * @return
  249. * TRUE if a redirect was created, or FALSE otherwise.
  250. */
  251. function path_redirect_check_alias_changed($path, $new_alias, $language = '') {
  252. if (!variable_get('path_redirect_auto_redirect', 1) || empty($new_alias)) {
  253. return FALSE;
  254. }
  255. $old_alias = drupal_get_path_alias($path, $language);
  256. if ($old_alias != $path && $old_alias != $new_alias) {
  257. // If the user is manually changing the path alias, add a redirect from the old alias to the node.
  258. $redirect = array(
  259. 'source' => $old_alias,
  260. 'redirect' => $path,
  261. //'language' => $language,
  262. );
  263. path_redirect_save($redirect);
  264. return $redirect;
  265. }
  266. }
  267. /**
  268. * Implements hook_taxonomy().
  269. */
  270. function path_redirect_taxonomy($op, $type, $array = NULL) {
  271. if ($op == 'delete' && $type == 'term') {
  272. // Delete any redirects to valid taxonomy paths.
  273. $term = (object) $array;
  274. $term_uri = taxonomy_term_path($term);
  275. path_redirect_delete_multiple(NULL, array('source' => $term_uri));
  276. path_redirect_delete_multiple(NULL, array('redirect' => $term_uri));
  277. if ($term_uri != "taxonomy/term/{$term->tid}") {
  278. path_redirect_delete_multiple(NULL, array('source' => "taxonomy/term/{$term->tid}"));
  279. path_redirect_delete_multiple(NULL, array('redirect' => "taxonomy/term/{$term->tid}"));
  280. }
  281. }
  282. }
  283. /**
  284. * Implements hook_user().
  285. */
  286. function path_redirect_user($op, &$edit, &$account, $category = NULL) {
  287. if ($op == 'delete') {
  288. // Delete any redirects to valid user paths.
  289. path_redirect_delete_multiple(NULL, array('source' => 'user/'. $account->uid));
  290. path_redirect_delete_multiple(NULL, array('redirect' => 'user/'. $account->uid));
  291. }
  292. }
  293. /**
  294. * Save an URL redirect to the database.
  295. */
  296. function path_redirect_save(&$redirect) {
  297. // Merge default values.
  298. $redirect += array(
  299. 'rid' => NULL,
  300. 'query' => '',
  301. 'fragment' => '',
  302. 'language' => '',
  303. 'type' => variable_get('path_redirect_default_status', 301),
  304. 'last_used' => time(),
  305. );
  306. // Convert query arrays into a saveable query string.
  307. if (isset($redirect['source_query']) && is_array($redirect['source_query'])) {
  308. $redirect['source'] .= '?' . drupal_query_string_encode($redirect['source_query']);
  309. }
  310. if (is_array($redirect['query'])) {
  311. $redirect['query'] = drupal_query_string_encode($redirect['query']);
  312. }
  313. // Allow spaces in "from" path
  314. // @todo Move to validation?
  315. $redirect['source'] = str_replace('+', ' ', $redirect['source']);
  316. // Remove beginning and trailing slashes from path.
  317. // @todo Move to validation?
  318. $redirect['source'] = trim($redirect['source'], '\/?');
  319. path_redirect_clear_cache();
  320. if (empty($redirect['rid'])) {
  321. drupal_write_record('path_redirect', $redirect);
  322. module_invoke_all('path_redirect_insert', $redirect);
  323. }
  324. else {
  325. drupal_write_record('path_redirect', $redirect, array('rid'));
  326. module_invoke_all('path_redirect_update', $redirect);
  327. }
  328. return $redirect;
  329. }
  330. /**
  331. * Load a redirect by ID.
  332. *
  333. * @param $rid
  334. * An integer with the redirect ID.
  335. */
  336. function path_redirect_load($rid) {
  337. $redirect = path_redirect_load_multiple(array($rid));
  338. return $redirect ? reset($redirect) : FALSE;
  339. }
  340. /**
  341. * Load a redirect by incoming path and language.
  342. *
  343. * @param $source
  344. * The incoming path.
  345. * @param $language
  346. * An optional language code. If not provided this will examine all language-
  347. * neutral redirects.
  348. * @param $query
  349. * An optional query string to match.
  350. */
  351. function path_redirect_load_by_source($source, $language = '', $query = array()) {
  352. $where = $query ? "(source = '%s' OR source LIKE '%s%%')" : "source = '%s'";
  353. $args = $query ? array($source, $source . '?') : array($source);
  354. $args[] = $language;
  355. $rid_query = db_query("SELECT rid FROM {path_redirect} WHERE $where AND language IN ('%s', '') ORDER BY language DESC, source DESC, rid DESC", $args);
  356. $rids = array();
  357. while ($rid = db_result($rid_query)) {
  358. $rids[] = $rid;
  359. }
  360. if ($rids && $redirects = path_redirect_load_multiple($rids)) {
  361. // Narrow down the list of candidates.
  362. foreach ($redirects as $rid => $redirect) {
  363. if (!empty($redirect['source_query'])) {
  364. if (empty($query) || !path_redirect_compare_array($redirect['source_query'], $query)) {
  365. unset($redirects[$rid]);
  366. continue;
  367. }
  368. }
  369. // Add a case sensitive matches condition to be used in sorting.
  370. if ($source !== $redirect['source']) {
  371. $redirects[$rid]['weight'] = 1;
  372. }
  373. }
  374. if (!empty($redirects)) {
  375. // Sort the redirects in the proper order.
  376. uasort($redirects, '_path_redirect_uasort');
  377. // Allow other modules to alter the redirect candidates before selecting the top one.
  378. $context = array('language' => $language, 'query' => $query);
  379. drupal_alter('path_redirect_load_by_source', $redirects, $source, $context);
  380. return !empty($redirects) ? reset($redirects) : FALSE;
  381. }
  382. }
  383. return FALSE;
  384. }
  385. function path_redirect_load_multiple($rids = NULL, $conditions = array()) {
  386. if (isset($rids) && empty($rids)) {
  387. return array();
  388. }
  389. $query = array();
  390. _path_redirect_build_conditions($query, $rids, $conditions);
  391. $sql = "SELECT * FROM {path_redirect} WHERE " . implode(' AND ', $query['conditions']);
  392. $query = db_query($sql, $query['args']);
  393. $redirects = array();
  394. while ($redirect = db_fetch_array($query)) {
  395. // Unpack query strings into arrays.
  396. if (!isset($redirect['source_query']) || !is_array($redirect['source_query'])) {
  397. $parsed = parse_url($redirect['source']) + array('query' => '');
  398. $redirect['source_query'] = path_redirect_get_query_array($parsed['query']);
  399. $redirect['source'] = $parsed['path'];
  400. }
  401. $redirect['query'] = path_redirect_get_query_array($redirect['query']);
  402. $redirects[$redirect['rid']] = $redirect;
  403. }
  404. return $redirects;
  405. }
  406. /**
  407. * uasort callback; Compare redirects based on language neutrality and rids.
  408. */
  409. function _path_redirect_uasort($a, $b) {
  410. $a_weight = isset($a['weight']) ? $a['weight'] : 0;
  411. $b_weight = isset($b['weight']) ? $b['weight'] : 0;
  412. if ($a_weight != $b_weight) {
  413. // First sort by weight (case sensitivity).
  414. return $a_weight > $b_weight;
  415. }
  416. elseif ($a['language'] != $b['language']) {
  417. // Then sort by language specific over language neutral.
  418. return $a['language'] == '';
  419. }
  420. elseif (empty($a['source_query']) != empty($b['source_query'])) {
  421. // Then sort by redirects that do not have query strings over ones that do.
  422. return empty($a['source_query']);
  423. }
  424. else {
  425. // Lastly sort by the highest redirect ID.
  426. return $a['rid'] < $b['rid'];
  427. }
  428. }
  429. function _path_redirect_build_conditions(&$query, $rids, $conditions) {
  430. static $schema;
  431. if (!isset($schema)) {
  432. $schema = !defined('MAINTENANCE_MODE') ? drupal_get_schema('path_redirect') : drupal_get_schema_unprocessed('path_redirect', 'path_redirect');
  433. }
  434. $query += array(
  435. 'conditions' => array(),
  436. 'args' => array(),
  437. );
  438. if ($rids) {
  439. $conditions += array('rid' => array());
  440. $conditions['rid'] = array_merge($rids, (array) $conditions['rid']);
  441. }
  442. if ($conditions) {
  443. foreach ($conditions as $field => $value) {
  444. if (!is_string($field) || !isset($schema['fields'][$field])) {
  445. continue;
  446. }
  447. //if ($field == 'langauge' && !is_array($value)) {
  448. // $value = array($value, '');
  449. //}
  450. $type = $schema['fields'][$field]['type'];
  451. if (is_array($value)) {
  452. $conditions[$field] = "$field IN (" . db_placeholders($value, $type) . ')';
  453. $query['args'] = array_merge($query['args'], $value);
  454. }
  455. else {
  456. $conditions[$field] = "$field = " . db_type_placeholder($type);
  457. $query['args'][] = $value;
  458. }
  459. }
  460. }
  461. $query['conditions'] = array_merge($query['conditions'], $conditions);
  462. return $query;
  463. }
  464. function path_redirect_clear_cache() {
  465. cache_clear_all(NULL, 'cache_page');
  466. }
  467. /**
  468. * Delete a redirect.
  469. *
  470. * @param $rid
  471. * The ID of the redirect to delete.
  472. */
  473. function path_redirect_delete($rid, $deprecated = FALSE) {
  474. // @todo Remove legacy path_redirect_delete support for pathauto.
  475. if (is_string($rid) && is_string($deprecated)) {
  476. return path_redirect_delete_multiple(NULL, array('source' => $rid, 'redirect' => $deprecated));
  477. }
  478. elseif (is_array($rid) && !isset($rid['rid'])) {
  479. $rid = $rid['rid'];
  480. }
  481. return path_redirect_delete_multiple(array($rid));
  482. }
  483. /**
  484. * Delete multiple redirects.
  485. *
  486. * @param $rids
  487. * An optional array or redirect IDs.
  488. * @param $conditions
  489. * An optional array of conditions keyed by field to match.
  490. * @return
  491. * The number of deleted redirects.
  492. */
  493. function path_redirect_delete_multiple($rids = NULL, $conditions = array()) {
  494. if ($redirects = path_redirect_load_multiple($rids, $conditions)) {
  495. foreach ($redirects as $redirect) {
  496. module_invoke_all('path_redirect_delete', $redirect);
  497. }
  498. }
  499. $query = array();
  500. _path_redirect_build_conditions($query, $rids, $conditions);
  501. $sql = 'DELETE FROM {path_redirect} WHERE ' . implode(' AND ', $query['conditions']);
  502. db_query($sql, $query['args']);
  503. $deleted = db_affected_rows();
  504. path_redirect_clear_cache();
  505. return $deleted;
  506. }
  507. function path_redirect_get_path($path = NULL) {
  508. if (!isset($path)) {
  509. if (drupal_is_front_page()) {
  510. $path = '<front>';
  511. }
  512. else {
  513. $path = $_GET['q'];
  514. }
  515. }
  516. else {
  517. if ($path == drupal_get_normal_path(variable_get('site_frontpage', 'node'))) {
  518. $path = '<front>';
  519. }
  520. }
  521. return $path;
  522. }
  523. function path_redirect_get_query($query = NULL) {
  524. if (!isset($query)) {
  525. $query = $_GET;
  526. }
  527. unset($query['q']);
  528. return $query;
  529. }
  530. function path_redirect_build_url($path, $query = '', $fragment = '', $clean_url = NULL) {
  531. if (!isset($clean_url)) {
  532. $clean_url = variable_get('clean_url', 0);
  533. }
  534. $url = $path;
  535. if ($query) {
  536. $url .= $clean_url ? '?' : '&';
  537. if (is_array($query)) {
  538. $url .= drupal_query_string_encode($query);
  539. }
  540. else {
  541. $url .= $query;
  542. }
  543. }
  544. if ($fragment) {
  545. $url .= '#' . $fragment;
  546. }
  547. return $url;
  548. }
  549. /**
  550. * Compare tha all values and associations in one array match another array.
  551. *
  552. * We cannot use array_diff_assoc() here because we need to be recursive.
  553. *
  554. * @param $match
  555. * The array that has the values.
  556. * @param $haystack
  557. * The array that will be searched for values.
  558. */
  559. function path_redirect_compare_array($match, $haystack) {
  560. foreach ($match as $key => $value) {
  561. if (!array_key_exists($key, $haystack)) {
  562. return FALSE;
  563. }
  564. elseif (is_array($value)) {
  565. if (!is_array($haystack[$key])) {
  566. return FALSE;
  567. }
  568. elseif (!path_redirect_compare_array($value, $haystack[$key])) {
  569. return FALSE;
  570. }
  571. }
  572. elseif ($value != $haystack[$key]) {
  573. return FALSE;
  574. }
  575. }
  576. return TRUE;
  577. }
  578. /**
  579. * Split an URL-encoded query string into an array.
  580. *
  581. * @param $query
  582. * The query string to split.
  583. *
  584. * @return
  585. * An array of url decoded couples $param_name => $value.
  586. */
  587. function path_redirect_get_query_array($query) {
  588. $result = array();
  589. if (!empty($query)) {
  590. foreach (explode('&', $query) as $param) {
  591. $param = explode('=', $param);
  592. $result[$param[0]] = isset($param[1]) ? rawurldecode($param[1]) : '';
  593. }
  594. }
  595. return $result;
  596. }
  597. function path_redirect_variables() {
  598. return array(
  599. 'path_redirect_redirect_warning' => 0,
  600. 'path_redirect_allow_bypass' => 0,
  601. 'path_redirect_auto_redirect' => 1,
  602. 'path_redirect_purge_inactive' => 0,
  603. 'path_redirect_default_status' => 301,
  604. 'path_redirect_nodeapi_enabled' => NULL,
  605. );
  606. }