Ed9c50a6db8b5e078b5ef84306a8477c

a) define a list of MIME types and their corresponding local formats.
b) parse the HTTP Accept headers and pick the available format with the highest q value.

The explode parameter might not be enough - can there be spaces and other characters, not just ',' and ';q='?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
function parse_accept_headers($default = 'html'){
  $formats = array(
    'text/html' => 'html',
    'application/xhtml+xml' => 0,
    'application/xml' => 0,
    '*/*' => 'html',
    );

  $accept = array();
  foreach (explode(',', $_SERVER['HTTP_ACCEPT']) as $header){
    $parts = explode(';q=', $header);
    if (count($parts) === 1)
      $parts[1] = 1;
    $accept[$parts[0]] = $parts[1];
  }

  arsort($accept);
  $accept[] = $default;

  foreach ($accept as $format => $q)
    if (array_key_exists($format, $formats) && $formats[$format])
      break;
  
  return array($format, $formats[$format]);
}

Refactorings

No refactoring yet !

1bf59120892e34eb60836725566c6e55

fain182.myopenid.com

January 9, 2009, January 09, 2009 16:40, permalink

1 rating. Login to rate!

slightly improved..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function parse_accept_headers($default = 'html'){
  $formats = array(
    'text/html' => 'html',
    'application/xhtml+xml' => 0,
    'application/xml' => 0,
    '*/*' => 'html',
    );

  $accept = array();
  foreach (explode(',', $_SERVER['HTTP_ACCEPT']) as $header){
    list($mime, $q) = explode(';q=', $header);
    $accept[$mime] = ($q === null)? 1 : $q;
  }
  arsort($accept);
  $accept[] = $default;

  foreach ($accept as $format => $q)
    if ($formats[$format])
        break;

  return array($format, $formats[$format]);
}
A8d3f35baafdaea851914b17dae9e1fc

Adam

January 9, 2009, January 09, 2009 22:27, permalink

No rating. Login to rate!

To answer your question about valid characters, the spec is here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php
function parse_accept_headers($default = 'html')
{
    return preferred_mime_type($_SERVER['HTTP_ACCEPT'], $default);
}

function preferred_mime_type($accept_header, $default = 'html')
{
    $formats = array(
        'text/html' => 'html',
        'application/xhtml+xml' => 0,
        'application/xml' => 0,
        '*/*' => 'html'
    );
    
    foreach (parse_accept_header($accept_header) as list($mime_type, $q)) {
        if ($formats[$mime_type] == $default) {
            return array($mime_type, $default);
        }
    }
    
    return array(0, null);
}

function parse_accept_header($accept_header)
{
    $accept_types = array_map(parse_accept_type, parse_accept_types($accept_header));    
    asort($accept_types);    
    return $accept_types;
}

function parse_accept_types($accept_types)
{
    return preg_split('/,\s*/', $accept_types);
}

function parse_accept_type($accept_type)
{
    list($mime_type, $q) = preg_split('/;\s*q=/', $accept_type);
    return array($mime_type, $q ? $q : 1);
}
?>
1750f7c621e3bc00b526335a836dd780

Todd

May 27, 2009, May 27, 2009 08:46, permalink

No rating. Login to rate!

Just a tiny tweak to Adam's code, to remove the mime reference from parse_accept_type() so that parse_accept_header() and lower methods can also be used to parse HTTPAcceptLanguage headers, without the mime-specific reference found there. These could then also be called, for example, from a preferred_language() function similar to how preferred_mime_type() uses them now. It may be pedantic, but it does illustrate that this can be expanded beyond mime types. :)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php
function parse_accept_headers($default = 'html')
{
    return preferred_mime_type($_SERVER['HTTP_ACCEPT'], $default);
}

function preferred_mime_type($accept_header, $default = 'html')
{
    $formats = array(
        'text/html' => 'html',
        'application/xhtml+xml' => 0,
        'application/xml' => 0,
        '*/*' => 'html'
    );
    
    foreach (parse_accept_header($accept_header) as list($mime_type, $q)) {
        if ($formats[$mime_type] == $default) {
            return array($mime_type, $default);
        }
    }
    
    return array(0, null);
}

function parse_accept_header($accept_header)
{
    $accept_types = array_map(parse_accept_type, parse_accept_types($accept_header));    
    asort($accept_types);    
    return $accept_types;
}

function parse_accept_types($accept_types)
{
    return preg_split('/,\s*/', $accept_types);
}

function parse_accept_type($accept_type)
{
    list($type, $q) = preg_split('/;\s*q=/', $accept_type);
    return array($type, $q ? $q : 1);
}
?>
A5d6ca1107e75169a207f106b6f8d95c

Alex Trauzzi

July 18, 2009, July 18, 2009 15:52, permalink

No rating. Login to rate!

For simplicity's sake, here's generating a key/value pair of mime types/values. Not much in the ways of validation, a worthwhile discussion awaits when it comes to whitespace...

Quick and dirty!

1
2
3
4
5
6
7
	$AcceptViews = array();
	// Build an array of the accept entries.
	foreach(explode(",", $_SERVER['HTTP_ACCEPT']) as $value) {
		$acceptLine = explode(";", $value);
		$AcceptViews[$acceptLine[0]] = floatval(array_key_exists(1, $acceptLine) ? substr($acceptLine[1], 2) : 1);
	}
	arsort($AcceptViews);

Your refactoring





Format Copy from initial code

or Cancel