/[drupal]/contributions/modules/path_redirect/path_redirect.admin.inc
ViewVC logotype

Contents of /contributions/modules/path_redirect/path_redirect.admin.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.6 - (show annotations) (download) (as text)
Wed Mar 18 02:53:37 2009 UTC (8 months, 1 week ago) by davereid
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +10 -5 lines
File MIME type: text/x-php
by Dave Reid: More syncs with 6.x. Added path_redirect_generate.module.
1 <?php
2 // $Id: path_redirect.admin.inc,v 1.5 2009/03/18 02:44:34 davereid Exp $
3
4 /**
5 * @file
6 * Administrative page callbacks for the path_redirect module.
7 */
8
9 /**
10 * Render a list of redirects for the main admin page.
11 */
12 function path_redirect_admin() {
13 $multilanguage = (module_exists('locale') || db_query("SELECT rid FROM {path_redirect} WHERE language <> ''")->fetchField());
14 $languages = language_list();
15
16 $header = array(
17 array('data' => t('From'), 'field' => 'path', 'sort' => 'asc'),
18 array('data' => t('To'), 'field' => 'redirect'),
19 array('data' => t('Type'), 'field' => 'type'),
20 array('data' => t('Operations'), 'colspan' => '2'),
21 );
22 if ($multilanguage) {
23 array_splice($header, 3, 0, array(array('data' => t('Language'), 'field' => 'language')));
24 }
25 $rows = array();
26 $limit = 50;
27
28 $query = db_select('path_redirect', 'pr');
29 $query->fields('pr', array('rid', 'path', 'redirect', 'query', 'fragment', 'language', 'type'));
30 $query = $query->extend('PagerDefault')->limit($limit);
31 $query = $query->extend('TableSort')->setHeader($header);
32 $redirects = $query->execute();
33
34 foreach ($redirects as $r) {
35 $redirect = url($r->redirect, array('query' => $r->query, 'fragment' => $r->fragment, 'absolute' => TRUE, 'alias' => TRUE));
36 $row = array(
37 'data' => array(
38 // @todo: Revise the following messy, confusing line.
39 l($r->path, preg_replace('/[\?\&].*/', '', $r->path), array('query' => strstr($r->path, '?') ? preg_replace('/.*\?/', '', $r->path) : NULL, 'language' => $r->language ? $languages[$r->language] : NULL)),
40 // @todo: Fix sorting on the redirect field
41 l($redirect, $redirect, array('external' => TRUE)),
42 $r->type,
43 l(t('Edit'), 'admin/build/path-redirect/edit/' . $r->rid, array('query' => drupal_get_destination())),
44 l(t('Delete'), 'admin/build/path-redirect/delete/' . $r->rid, array('query' => drupal_get_destination())),
45 ),
46 );
47 if ($multilanguage) {
48 array_splice($row['data'], 3, 0, module_invoke('locale', 'language_name', $r->language));
49 }
50 $rows[] = $row;
51 }
52
53 if (empty($rows)) {
54 $rows[] = array(array('data' => t('No redirects available.'), 'colspan' => $multilanguage ? 5 : 4));
55 }
56
57 $build['table'] = array(
58 '#markup' => theme('table', $header, $rows, array('class' => 'path-redirects')),
59 );
60 $build['pager'] = array(
61 '#markup' => theme('pager', NULL, $limit),
62 );
63
64 return drupal_get_page($build);
65 }
66
67 /**
68 * Callback for add and edit pages.
69 *
70 * @return
71 * A form for drupal_get_form.
72 */
73 function path_redirect_edit($form_state, $rid = FALSE) {
74 if ($rid) {
75 $redirect = (array) path_redirect_load($rid);
76 drupal_set_title(check_plain($redirect['path']));
77 $output = path_redirect_edit_form($form_state, $redirect);
78 }
79 else {
80 drupal_set_title(t('Add redirect'));
81 $output = path_redirect_edit_form($form_state);
82 }
83 return $output;
84 }
85
86 function path_redirect_edit_form(&$form_state, $edit = array()) {
87 // Merge default values.
88 $_GET += array(
89 'src' => '',
90 'dst' => '',
91 'language' => '',
92 );
93 $edit += array(
94 'rid' => NULL,
95 'path' => urldecode($_GET['src']),
96 'redirect' => urldecode($_GET['dst']),
97 'query' => NULL,
98 'fragment' => NULL,
99 'language' => urldecode($_GET['language']),
100 'type' => path_redirect_var('default_status'),
101 );
102
103 $form['path'] = array(
104 '#type' => 'textfield',
105 '#title' => t('From'),
106 '#description' => t("Enter an interal Drupal path or path alias to redirect (e.g. %example1 or %example2). Fragment anchors (e.g. %anchor) are <strong>not</strong> allowed.", array('%example1' => 'node/123', '%example2' => 'taxonomy/term/123', '%anchor' => '#anchor')),
107 '#size' => 42,
108 '#maxlength' => 255,
109 '#default_value' => $edit['path'],
110 '#required' => TRUE,
111 '#field_prefix' => url('', array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q='),
112 '#autocomplete_path' => db_table_exists('watchdog') ? 'admin/build/path-redirect/autocomplete' : '',
113 );
114
115 $form['redirect'] = array(
116 '#type' => 'item',
117 '#prefix' => '<div class="container-inline">',
118 '#suffix' => '</div>',
119 '#title' => t('To'),
120 '#description' => '<div style="display:block">' . t('Enter an interal Drupal path, path alias, or complete external URL (like http://example.com/) to redirect to. Use %front to redirect to the front page. Enter (optional) queries after "?" and (optional) anchor after "#". Most redirects will not contain queries or fragment anchors.', array('%front' => '<front>')) . '</div>',
121 );
122
123 $form['redirect']['redirect'] = array(
124 '#type' => 'textfield',
125 '#size' => 30,
126 '#maxlength' => 255,
127 '#default_value' => $edit['redirect'],
128 //'#required' => TRUE,
129 );
130
131 $form['redirect'][] = array(
132 '#value' => '?',
133 );
134
135 $form['redirect']['query'] = array(
136 '#type' => 'textfield',
137 '#size' => 12,
138 '#maxlength' => 255,
139 '#default_value' => $edit['query'],
140 );
141
142 $form['redirect'][] = array(
143 '#value' => '#',
144 );
145
146 $form['redirect']['fragment'] = array(
147 '#type' => 'textfield',
148 '#size' => 12,
149 '#maxlength' => 50,
150 '#default_value' => $edit['fragment'],
151 );
152
153 $form[] = array(
154 '#value' => "<p> </p>", // little bit of extra space
155 );
156
157 $form['language'] = array(
158 '#type' => 'value',
159 '#title' => t('Language'),
160 '#options' => array('' => t('All languages')),
161 '#default_value' => $edit['language'],
162 '#description' => t('A redirect set for a specific language will always be used when requesting this page in that language, and takes precedence over redirects set for <em>All languages</em>.'),
163 );
164 if (module_exists('locale')) {
165 $form['language']['#type'] = 'select';
166 $form['language']['#options'] += locale_language_list('name');
167 }
168
169 $form['advanced'] = array(
170 '#type' => 'fieldset',
171 '#title' => t('Advanced options'),
172 '#collapsible' => TRUE,
173 '#collapsed' => TRUE,
174 );
175
176 $status_options = array();
177 $status_descriptions = array();
178 foreach (path_redirect_status_codes() as $code => $details) {
179 $status_options[$code] = $details['title'];
180 $status_descriptions[] = $details['title'] . ': ' . $details['description'];
181 }
182 $form['advanced']['type'] = array(
183 '#type' => 'select',
184 '#title' => t('Redirect status'),
185 '#description' => theme('item_list', $status_descriptions) . t('You can find more information about HTTP redirect status codes at <a href="@link">@link</a>.', array('@link' => 'http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3')),
186 '#default_value' => $edit['type'],
187 '#options' => $status_options,
188 );
189
190 $form['rid'] = array('#type' => 'value', '#value' => $edit['rid']);
191 $form['submit'] = array('#type' => 'submit', '#value' => t('Save'));
192 $form['cancel'] = array('#value' => l(t('Cancel'), 'admin/build/path-redirect'));
193 $form['#redirect'] = 'admin/build/path-redirect';
194
195 return $form;
196 }
197
198 function path_redirect_edit_validate($form, &$form_state) {
199 if (strpos($form_state['values']['path'], '#') !== FALSE) {
200 // Check that the "from" path is valid and contains no # fragment
201 form_set_error('path', t('You cannot redirect from a fragment anchor.'));
202 }
203 //elseif (!valid_url($form_state['values']['path'])) {
204 // //Make sure "from" has the form of a local Drupal path
205 // form_set_error('path', t('The redirect <strong>from</strong> path does not appear valid. This must be a local Drupal path.'));
206 //}
207 elseif (($result = path_redirect_load(array('path' => $form_state['values']['path']))) && $form_state['values']['rid'] !== $result->rid) {
208 // The "from" path should not conflict with another redirect
209 form_set_error('path', t('The <strong>from</strong> path you entered is already redirected. You can <a href="@edit-page">edit this redirect</a> instead.', array('@edit-page' => url('admin/build/path-redirect/edit/' . $result->rid))));
210 }
211 //elseif (db_result(db_query("SELECT * FROM {url_alias} WHERE dst = '%s'", array(':dst' => $form_state['values']['path'])))) {
212 // // A redirect's 'from' cannot match any values from url_alias, it will cause an infinite loop.
213 // form_set_error('path', t('The path you entered will cause an infinite loop.'));
214 //}
215
216 if (!valid_url($form_state['values']['redirect']) && !valid_url($form_state['values']['redirect'], TRUE) && $form_state['values']['redirect'] != '<front>') {
217 form_set_error('redirect', t('The redirect <strong>to</strong> path does not appear valid.'));
218 }
219
220 if ($form_state['values']['redirect'] == '<front>') {
221 $form_state['values']['redirect'] = variable_get('site_frontpage', 'node');
222 }
223
224 // check that there there are no redirect loops
225 if ($form_state['values']['path'] === $form_state['values']['redirect']) {
226 form_set_error('redirect', t('You are attempting to redirect the page to itself. This will result in an infinite loop.'));
227 }
228
229 // Allow spaces in "from" path
230 $form_state['values']['path'] = str_replace("+", " ", $form_state['values']['path']);
231 }
232
233 function path_redirect_edit_submit($form, &$form_state) {
234 path_redirect_save($form_state['values']);
235 drupal_set_message(t('Redirect has been saved.'));
236 }
237
238 function path_redirect_delete_confirm($form_state, $rid) {
239 $form['rid'] = array(
240 '#type' => 'value',
241 '#value' => $rid,
242 );
243 $redirect = path_redirect_load($rid);
244 return confirm_form($form,
245 t('Are you sure you want to delete the redirect from %path to %redirect?', array('%path' => $redirect->path, '%redirect' => $redirect->redirect)),
246 isset($_GET['destination']) ? $_GET['destination'] : 'admin/build/path-redirect');
247 }
248
249 function path_redirect_delete_confirm_submit($form, &$form_state) {
250 if ($form_state['values']['confirm']) {
251 path_redirect_delete($form_state['values']['rid']);
252 drupal_set_message(t('The redirect has been deleted.'));
253 }
254 }
255
256 /**
257 * Form builder; administrative settings for the module.
258 *
259 * @see system_settings_form()
260 */
261 function path_redirect_settings_form() {
262 $form['path_redirect_redirect_warning'] = array(
263 '#type' => 'checkbox',
264 '#title' => t('Display a warning message to users when they are redirected.'),
265 '#default_value' => path_redirect_var('redirect_warning'),
266 );
267
268 $form['path_redirect_allow_bypass'] = array(
269 '#type' => 'checkbox',
270 '#title' => t('Allow users to bypass redirects by adding %code to the URL.', array('%code' => variable_get('clean_url', 0) ? '?redirect=no' : '&redirect=no')),
271 '#default_value' => path_redirect_var('allow_bypass'),
272 );
273
274 $form['path_redirect_auto_redirect'] = array(
275 '#type' => 'checkbox',
276 '#title' => t('Automatically create redirects when URL aliases are changed.'),
277 '#default_value' => path_redirect_var('auto_redirect'),
278 '#access' => module_exists('path'),
279 );
280
281 $form['path_redirect_purge_inactive'] = array(
282 '#type' => 'select',
283 '#title' => t('Discard redirects that have not been accessed for'),
284 '#default_value' => path_redirect_var('purge_inactive'),
285 '#options' => array(0 => t('Never (do not discard)')) + drupal_map_assoc(array(604800, 1209600, 2419200, 4838400, 7257600, 9676800, 31536000), 'format_interval'),
286 );
287
288 $status_options = array();
289 $status_descriptions = array();
290 foreach (path_redirect_status_codes() as $code => $details) {
291 $status_options[$code] = $details['title'];
292 $status_descriptions[] = $details['title'] . ': ' . $details['description'];
293 }
294 $form['path_redirect_default_status'] = array(
295 '#type' => 'select',
296 '#title' => t('Default redirect status'),
297 '#description' => theme('item_list', $status_descriptions) . t('You can find more information about HTTP redirect status codes at <a href="@link">@link</a>.', array('@link' => 'http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3')),
298 '#default_value' => path_redirect_var('default_status'),
299 '#options' => $status_options,
300 );
301
302 return system_settings_form($form);
303 }
304
305 /**
306 * Return an array of 300-range status codes.
307 */
308 function path_redirect_status_codes() {
309 return array(
310 300 => array(
311 'title' => t('300 Multiple Choices'),
312 'description' => t('The request is ambiguous and needs clarification as to which resource was requested.'),
313 ),
314 301 => array(
315 'title' => t('301 Moved Permanently'),
316 'description' => t('Moved Permanently. The resource has permanently moved elsewhere, the response indicates where it has gone to. <strong>Recommended.</strong>'),
317 ),
318 302 => array(
319 'title' => t('302 Found'),
320 'description' => t("The resource has temporarily moved elsewhere, the response indicates where it is at present. <strong>This is Drupal's default redirect type.</strong>"),
321 ),
322 303 => array(
323 'title' => t('303 See Other'),
324 'description' => t('See Other/Redirect. A preferred alternative source should be used at present.'),
325 ),
326 304 => array(
327 'title' => t('304 Not Modified'),
328 'description' => t("The server has identified from the request information that the client's copy of the information is up-to-date and the requested information does not need to be sent again."),
329 ),
330 305 => array(
331 'title' => t('305 Use Proxy'),
332 'description' => t('The request must be sent through the indicated proxy server.'),
333 ),
334 307 => array(
335 'title' => t('307 Temporary Redirect'),
336 'description' => t('The resource has temporarily moved elsewhere, the response indicates where it is at present. Client should still use this URL.'),
337 ),
338 );
339 }
340
341 /*
342 * Extract part of the current Drupal path from a certain 'argument' onward.
343 *
344 * @todo Replace with drupal_get_path_segment in Drupal 7.
345 */
346 function path_redirect_get_path_segment($index = 0) {
347 $path = trim($_GET['q']);
348 $path = explode('/', $path, $index + 1);
349 $path = (count($path) > $index ? end($path) : '');
350 return $path;
351 }
352
353 /**
354 * Autocompletion callback for the add/edit redirect form. Returns a list of
355 * current 404s on the site.
356 */
357 function path_redirect_autocomplete() {
358 $string = path_redirect_get_path_segment(4);
359 $matches = array();
360
361 // Get a list of 404s, sorted by the number of times each 404 was processed.
362 $paths = db_query("SELECT message, COUNT(message) AS count FROM {watchdog} WHERE type = 'page not found' AND LOWER(message) LIKE :message GROUP BY message ORDER BY count DESC", array(':message' => '%' . drupal_strtolower($string) . '%'))->fetchCol();
363 foreach ($paths as $path) {
364 // If the 404 is now a valid path or already has a redirect, discard it.
365 if (!menu_get_item($path) && !path_redirect_load(array('path' => $path))) {
366 $matches[$path] = check_plain($path);
367 }
368 }
369
370 // Limit the output to 10 results and return the JSON.
371 $matches = array_slice($matches, 0, 10);
372 drupal_json($matches);
373 }
374
375 /**
376 * Form builder; an import form for redirects.
377 *
378 * @see path_redirect_import_form_submit()
379 */
380 function path_redirect_import_form() {
381 $form['file'] = array(
382 '#type' => 'file',
383 '#title' => t('Upload import file'),
384 '#size' => 50,
385 );
386 $form['type'] = array(
387 '#type' => 'radios',
388 '#title' => t('File format'),
389 '#options' => array(
390 'auto' => t('Auto detect'),
391 'csv' => t('CSV (Tab-delimited)'),
392 'xml' => t('XML'),
393 ),
394 '#default_value' => 'auto',
395 );
396 $form['mode'] = array(
397 '#type' => 'radios',
398 '#title' => t('Mode'),
399 '#description' => t('What action should be taken when there are duplicate redirects?'),
400 '#options' => array(
401 'overwrite' => t('Redirects in the uploaded file replace existing ones, new ones are added.'),
402 'keep' => t('Existing redirects are kept, only new redirects are added.')
403 ),
404 '#default_value' => 'keep',
405 );
406 $form['submit'] = array(
407 '#type' => 'submit',
408 '#value' => t('Import'),
409 );
410 $form['#attributes']['enctype'] = 'multipart/form-data';
411
412 return $form;
413 }
414
415 /**
416 * Handles redirect import.
417 *
418 * @see path_redirect_import_form()
419 * @see path_redirect_import_csv()
420 * @see path_redirect_import_xml()
421 */
422 function path_redirect_import_form_submit($form, $form_state) {
423 if ($file = file_save_upload('file')) {
424 $type = $form_state['values']['type'];
425
426 if ($type == 'auto') {
427 if ($file->filemime == 'text/csv' || substr($file->filename, -4) == '.csv') {
428 $type = 'csv';
429 }
430 elseif (strpos($file->filemime, 'xml') !== FALSE || substr($file->filename, -4) == '.xml') {
431 $type = 'xml';
432 }
433 else {
434 drupal_set_message(t('Could not determine the correct file type. Please select the file format manually and check the import file.'), 'error');
435 return;
436 }
437 }
438
439 $function = 'path_redirect_import_'. $type;
440 if ($text = @file_get_contents($file->filepath)) {
441 $function($text);
442 }
443 else {
444 drupal_set_message(t('Could not import file.'), 'error');
445 }
446 }
447 else {
448 drupal_set_message(t('Import file not found.'), 'error');
449 }
450 }
451
452 /**
453 * Imports redirects from a CSV file.
454 *
455 * @see path_redirect_import_form_submit()
456 */
457 function path_redirect_import_csv($file) {
458 }
459
460 /**
461 * Imports redirects from an XML file.
462 *
463 * @see path_redirect_import_form_submit()
464 */
465 function path_redirect_import_xml($file) {
466 $imports = simplexml_load_string($file);
467 }
468
469 /**
470 * Form builder;
471 */
472 function path_redirect_export_form() {
473 if (!db_result(db_query("SELECT COUNT(*) FROM {path_redirect}"))) {
474 drupal_set_message(t('No redirects available.'));
475 return;
476 }
477
478 $form['type'] = array(
479 '#type' => 'radios',
480 '#title' => t('Export format'),
481 '#options' => array(
482 'csv' => t('CSV (Tab-delimited)'),
483 'xml' => t('XML'),
484 ),
485 '#default_value' => 'csv',
486 );
487 $form['submit'] = array(
488 '#type' => 'submit',
489 '#value' => t('Export'),
490 );
491
492 return $form;
493 }
494
495 /**
496 * Handles redirect exporting.
497 *
498 * @see path_redirect_export_form()
499 * @see path_redirect_export_csv()
500 * @see path_redirect_export_xml()
501 */
502 function path_redirect_export_form_submit($form, $form_state) {
503 $type = $form_state['values']['type'];
504 $function = 'path_redirect_export_'. $type;
505
506 $filename = variable_get('site_name', 'Drupal') .' redirects '. format_date(REQUEST_TIME, 'custom', 'Y m d');
507 $filename = preg_replace(array('/^\W+|\W+$/', '/\W+/'), array('', '-'), drupal_strtolower($filename));
508 $filename .= '.'. $type;
509 drupal_set_header('Content-Disposition: attachment; filename='. $filename);
510
511 echo $function();
512 drupal_page_footer();
513 exit();
514 }
515
516 /**
517 * Exports redirects to a CSV format.
518 *
519 * @see path_redirect_export_form_submit()
520 */
521 function path_redirect_export_csv() {
522 drupal_set_header('Content-Type: text/csv; charset=utf-8');
523 $fields = array('path', 'redirect', 'query', 'fragment', 'language', 'type', 'last_used');
524 $redirects = db_query("SELECT ". implode(', ', $fields) ." FROM {path_redirect}");
525 $export = implode("\t", $fields) . PHP_EOL;
526 while ($redirect = db_fetch_array($redirects)) {
527 $export .= implode("\t", $redirect) . PHP_EOL;
528 }
529 return $export;
530 }
531
532 /**
533 * Exports redirects to a XML format.
534 *
535 * @see path_redirect_export_form_submit()
536 */
537 function path_redirect_export_xml() {
538 drupal_set_header('Content-Type: text/xml; charset=utf-8');
539 //$export = simplexml_load_string();
540 $export = new SimpleXMLElement("<?xml version=\"1.0\" encoding=\"utf-8\"?><redirects />");
541 $redirects = db_query("SELECT path, redirect, query, fragment, language, type, last_used FROM {path_redirect}");
542 while ($redirect = db_fetch_object($redirects)) {
543 $export_item = $export->addChild('redirect');
544 foreach ($redirect as $key => $value) {
545 if ($value != '' && $value !== NULL) {
546 $export_item->addAttribute($key, $value);
547 }
548 }
549 }
550 return $export->asXML();
551 }

  ViewVC Help
Powered by ViewVC 1.1.2