2001-12-01 15:20:48 +00:00
< ? php
2003-12-13 14:59:55 +00:00
/* $Id$ */
2001-12-01 15:20:48 +00:00
2004-07-13 07:21:14 +00:00
/**
* @ file
*
* Common functions that many Drupal modules will need to reference .
*
* The functions that are critical and need to be available even when serving
* a cached page are instead located in bootstrap . inc .
*/
2004-01-06 19:52:14 +00:00
/**
* @ name Page title
2003-12-08 06:32:19 +00:00
*
* Functions to get and set the title of the current page .
* @ {
*/
2003-11-23 10:41:04 +00:00
function drupal_set_title ( $title = NULL ) {
static $stored_title ;
if ( isset ( $title )) {
2003-11-25 19:26:21 +00:00
$stored_title = ucfirst ( $title );
2003-11-23 10:41:04 +00:00
}
return $stored_title ;
}
function drupal_get_title () {
$title = drupal_set_title ();
if ( ! isset ( $title )) {
$title = menu_get_active_title ();
}
return $title ;
}
2004-01-06 19:52:14 +00:00
/* @} */
2003-11-23 10:41:04 +00:00
/**
2004-01-06 19:52:14 +00:00
* @ name Page breadcrumbs
2003-12-08 06:32:19 +00:00
*
* Functions to get and set the breadcrumb trail of the current page .
* @ {
*/
2004-01-06 19:52:14 +00:00
/**
* @ param $breadcrumb Array of links , starting with " home " and proceeding up
* to but not including the current page .
*/
2003-11-23 10:41:04 +00:00
function drupal_set_breadcrumb ( $breadcrumb = NULL ) {
static $stored_breadcrumb ;
if ( isset ( $breadcrumb )) {
$stored_breadcrumb = $breadcrumb ;
}
return $stored_breadcrumb ;
}
function drupal_get_breadcrumb () {
$breadcrumb = drupal_set_breadcrumb ();
if ( ! isset ( $breadcrumb )) {
$breadcrumb = menu_get_active_breadcrumb ();
}
return $breadcrumb ;
}
2004-01-06 19:52:14 +00:00
/* @} */
2003-11-23 10:41:04 +00:00
2004-01-14 22:30:09 +00:00
/**
* @ name HTML head contents
*
* Set and get output that should be in the \ < head\ > tag .
* @ {
*/
function drupal_set_html_head ( $data = NULL ) {
2004-04-12 08:27:57 +00:00
static $stored_head = '' ;
2004-01-14 22:30:09 +00:00
if ( ! is_null ( $data )) {
2004-07-13 07:21:14 +00:00
$stored_head .= $data . " \n " ;
2004-01-14 22:30:09 +00:00
}
return $stored_head ;
}
function drupal_get_html_head () {
global $base_url ;
2004-01-29 06:47:19 +00:00
$output = " <meta http-equiv= \" Content-Type \" content= \" text/html; charset=utf-8 \" /> \n " ;
2004-01-14 22:30:09 +00:00
$output .= " <base href= \" $base_url / \" /> \n " ;
2004-01-29 06:47:19 +00:00
$output .= " <style type= \" text/css \" media= \" all \" > \n " ;
2004-01-14 22:30:09 +00:00
$output .= " @import url(misc/drupal.css); \n " ;
$output .= " </style> \n " ;
return $output . drupal_set_html_head ();
}
/* @} */
2003-09-30 17:01:34 +00:00
/**
2004-02-08 17:12:44 +00:00
* @ name URL path alias
2004-01-06 19:52:14 +00:00
*
2004-02-08 17:12:44 +00:00
* Functions to handle path aliases .
2003-12-08 06:32:19 +00:00
*/
2004-07-13 07:21:14 +00:00
function drupal_get_path_map ( $action = '' ) {
2003-12-13 14:59:55 +00:00
static $map = NULL ;
2003-09-30 17:01:34 +00:00
2004-07-13 07:21:14 +00:00
if ( $action == 'rebuild' ) {
2003-10-03 14:10:05 +00:00
$map = NULL ;
}
2003-12-13 14:59:55 +00:00
if ( is_null ( $map )) {
2004-01-25 09:09:00 +00:00
$map = array (); // make $map non-null in case no aliases are defined
2004-07-13 07:21:14 +00:00
$result = db_query ( 'SELECT * FROM {url_alias}' );
2003-09-30 17:01:34 +00:00
while ( $data = db_fetch_object ( $result )) {
2003-10-01 05:18:03 +00:00
$map [ $data -> dst ] = $data -> src ;
2003-09-30 17:01:34 +00:00
}
}
return $map ;
}
2003-10-03 14:10:05 +00:00
function drupal_rebuild_path_map () {
2004-07-13 07:21:14 +00:00
drupal_get_path_map ( 'rebuild' );
2003-10-03 14:10:05 +00:00
}
2004-01-06 19:52:14 +00:00
/**
2004-07-13 07:21:14 +00:00
* Given an internal Drupal path , return the alias set by the administrator .
2004-01-06 19:52:14 +00:00
*/
2004-02-08 17:12:44 +00:00
function drupal_get_path_alias ( $path ) {
if (( $map = drupal_get_path_map ()) && ( $newpath = array_search ( $path , $map ))) {
return $newpath ;
}
2004-07-13 07:21:14 +00:00
elseif ( function_exists ( 'conf_url_rewrite' )) {
2004-02-08 17:12:44 +00:00
return conf_url_rewrite ( $path , 'outgoing' );
}
2004-06-01 21:58:46 +00:00
else {
// No alias found. Return the normal path.
return $path ;
}
2004-02-08 17:12:44 +00:00
}
/**
2004-07-13 07:21:14 +00:00
* Given a path alias , return the internal path it represents .
2004-02-08 17:12:44 +00:00
*/
function drupal_get_normal_path ( $path ) {
if (( $map = drupal_get_path_map ()) && isset ( $map [ $path ])) {
return $map [ $path ];
}
2004-07-13 07:21:14 +00:00
elseif ( function_exists ( 'conf_url_rewrite' )) {
2004-02-08 17:12:44 +00:00
return conf_url_rewrite ( $path , 'incoming' );
}
else {
return $path ;
}
}
/* @} */
2004-01-06 19:52:14 +00:00
2004-01-14 22:30:09 +00:00
/**
* @ name HTTP headers
*
* Functions to get and set the HTTP headers of the current page .
* @ {
*/
function drupal_set_header ( $header = NULL ) {
2004-04-12 08:27:57 +00:00
static $stored_headers = '' ;
2004-01-14 22:30:09 +00:00
if ( ! is_null ( $header )) {
header ( $header );
2004-07-13 07:21:14 +00:00
$stored_headers .= $header . " \n " ;
2004-01-14 22:30:09 +00:00
}
return $stored_headers ;
}
function drupal_get_headers () {
return drupal_set_header ();
}
/* @} */
2004-02-08 17:12:44 +00:00
/**
* @ name HTTP handling
*
* Functions to properly handle HTTP responses .
* @ {
*/
2004-01-06 19:52:14 +00:00
/**
2004-07-11 07:31:11 +00:00
* Send the user to a different Drupal page .
2004-01-06 19:52:14 +00:00
*
2004-07-11 07:31:11 +00:00
* This issues an on - site HTTP redirect . The function makes sure the redirected
* URL is formatted correctly .
2004-01-06 19:52:14 +00:00
*
2004-07-11 07:31:11 +00:00
* It is advised to use drupal_goto () instead of PHP ' s header (), because
* drupal_goto () will append the user ' s session ID to the URI when PHP is
* compiled with " --enable-trans-sid " .
*
* This function ends the request ; use it rather than a print theme ( 'page' )
* statement in your menu callback .
*
* @ param $path
* A Drupal path .
* @ param $query
* The query string component , if any .
* @ param $fragment
* The destination fragment identifier ( named anchor ) .
2004-01-06 19:52:14 +00:00
*/
2004-07-11 07:31:11 +00:00
function drupal_goto ( $path = '' , $query = NULL , $fragment = NULL ) {
// Translate & to simply & in the absolute URL.
$url = str_replace ( '&' , '&' , url ( $path , $query , $fragment , TRUE ));
2004-01-06 19:52:14 +00:00
2004-07-11 07:31:11 +00:00
if ( ini_get ( 'session.use_trans_sid' ) && session_id () && ! strstr ( $url , session_id ())) {
$sid = session_name () . '=' . session_id ();
2003-10-03 14:10:05 +00:00
2004-07-11 07:31:11 +00:00
if ( strstr ( $url , '?' ) && ! strstr ( $url , $sid )) {
$url = $url . '&' . $sid ;
2004-01-06 19:52:14 +00:00
}
else {
2004-07-11 07:31:11 +00:00
$url = $url . '?' . $sid ;
2004-01-06 19:52:14 +00:00
}
}
2004-07-11 07:31:11 +00:00
// Before the redirect, allow modules to react to the end of the page request.
module_invoke_all ( 'exit' , $url );
header ( 'Location: ' . $url );
2004-01-06 19:52:14 +00:00
2004-07-11 07:31:11 +00:00
// The "Location" header sends a REDIRECT status code to the http
// daemon. In some cases this can go wrong, so we make sure none
// of the code below the drupal_goto() call gets executed when we redirect.
2004-01-06 19:52:14 +00:00
exit ();
}
/**
* Generates a 404 error if the request can not be handled .
*/
2003-12-16 21:06:34 +00:00
function drupal_not_found () {
2004-04-21 13:56:38 +00:00
header ( 'HTTP/1.0 404 Not Found' );
2004-07-13 07:21:14 +00:00
watchdog ( 'httpd' , t ( '404 error: "%page" not found' , array ( '%page' => check_query ( $_GET [ 'q' ]))));
2003-12-16 21:06:34 +00:00
$path = drupal_get_normal_path ( variable_get ( 'site_404' , '' ));
2004-07-02 18:46:42 +00:00
$status = MENU_NOT_FOUND ;
2003-12-16 21:06:34 +00:00
if ( $path ) {
menu_set_active_item ( $path );
2004-04-21 13:56:38 +00:00
$status = menu_execute_active_handler ();
2003-12-16 21:06:34 +00:00
}
2004-04-21 13:56:38 +00:00
if ( $status != MENU_FOUND ) {
2004-03-08 18:35:04 +00:00
print theme ( 'page' , '' , t ( 'Page not found' ));
2003-12-16 21:06:34 +00:00
}
}
2004-01-07 19:52:10 +00:00
2004-04-21 13:56:38 +00:00
/**
* Generates a 403 error if the request is not allowed .
*/
function drupal_access_denied () {
header ( 'HTTP/1.0 403 Forbidden' );
$path = drupal_get_normal_path ( variable_get ( 'site_403' , '' ));
2004-07-02 18:46:42 +00:00
$status = MENU_NOT_FOUND ;
2004-04-21 13:56:38 +00:00
if ( $path ) {
menu_set_active_item ( $path );
$status = menu_execute_active_handler ();
}
if ( $status != MENU_FOUND ) {
print theme ( 'page' , message_access (), t ( 'Access denied' ));
}
}
2004-01-07 19:52:10 +00:00
/**
2004-07-13 07:21:14 +00:00
* Perform an HTTP request .
2004-01-07 19:52:10 +00:00
*
2004-07-13 07:21:14 +00:00
* This is a flexible and powerful HTTP client implementation . Correctly handles
* GET , POST , PUT or any other HTTP requests . Handles redirects .
*
* @ param $url
* A string containing a fully qualified URI .
* @ param $headers
* An array containing an HTTP header => value pair .
* @ param $method
* A string defining the HTTP request to use .
* @ param $data
* A string containing data to include in the request .
* @ param $retry
* An integer representing how many times to retry the request in case of a
* redirect .
* @ return
* An object containing the HTTP request headers , response code , headers ,
* data , and redirect status .
2004-01-07 19:52:10 +00:00
*/
function drupal_http_request ( $url , $headers = array (), $method = 'GET' , $data = NULL , $retry = 3 ) {
2004-07-13 07:21:14 +00:00
// Parse the URL, and make sure we can handle the schema.
2004-01-07 19:52:10 +00:00
$uri = parse_url ( $url );
switch ( $uri [ 'scheme' ]) {
case 'http' :
$fp = @ fsockopen ( $uri [ 'host' ], ( $uri [ 'port' ] ? $uri [ 'port' ] : 80 ), $errno , $errstr , 15 );
break ;
case 'https' :
2004-07-13 07:21:14 +00:00
// Note: Only works for PHP 4.3 compiled with OpenSSL.
$fp = @ fsockopen ( 'ssl://' . $uri [ 'host' ], ( $uri [ 'port' ] ? $uri [ 'port' ] : 443 ), $errno , $errstr , 20 );
2004-01-07 19:52:10 +00:00
break ;
default :
2004-07-13 07:21:14 +00:00
$result -> error = 'invalid schema ' . $uri [ 'scheme' ];
2004-01-07 19:52:10 +00:00
return $result ;
}
2004-07-13 07:21:14 +00:00
// Make sure the socket opened properly.
2004-01-07 19:52:10 +00:00
if ( ! $fp ) {
2004-07-13 07:21:14 +00:00
$result -> error = trim ( $errno . ' ' . $errstr );
2004-01-07 19:52:10 +00:00
return $result ;
}
2004-07-13 07:21:14 +00:00
// Construct the path to act on.
2004-01-07 19:52:10 +00:00
$path = $uri [ 'path' ] ? $uri [ 'path' ] : '/' ;
if ( $uri [ 'query' ]) {
2004-07-13 07:21:14 +00:00
$path .= '?' . $uri [ 'query' ];
2004-01-07 19:52:10 +00:00
}
2004-07-13 07:21:14 +00:00
// Create http request.
2004-01-07 19:52:10 +00:00
$defaults = array (
2004-07-13 07:21:14 +00:00
'Host' => 'Host: ' . $uri [ 'host' ],
2004-01-07 20:43:26 +00:00
'User-Agent' => 'User-Agent: Drupal (+http://www.drupal.org/)' ,
'Content-Length' => 'Content-Length: ' . strlen ( $data )
2004-01-07 19:52:10 +00:00
);
foreach ( $headers as $header => $value ) {
2004-07-13 07:21:14 +00:00
$defaults [ $header ] = $header . ': ' . $value ;
2004-01-07 19:52:10 +00:00
}
2004-07-13 07:21:14 +00:00
$request = $method . ' ' . $path . " HTTP/1.0 \r \n " ;
2004-01-07 19:52:10 +00:00
$request .= implode ( " \r \n " , $defaults );
$request .= " \r \n \r \n " ;
if ( $data ) {
2004-07-13 07:21:14 +00:00
$request .= $data . " \r \n " ;
2004-01-07 19:52:10 +00:00
}
$result -> request = $request ;
fwrite ( $fp , $request );
// Fetch response.
2004-04-27 18:17:17 +00:00
$response = '' ;
2004-04-21 19:43:23 +00:00
while ( ! feof ( $fp ) && $data = fread ( $fp , 1024 )) {
2004-04-27 18:17:17 +00:00
$response .= $data ;
2004-01-07 19:52:10 +00:00
}
fclose ( $fp );
// Parse response.
2004-06-21 20:14:41 +00:00
list ( $headers , $result -> data ) = explode ( " \r \n \r \n " , $response , 2 );
$headers = preg_split ( " / \r \n | \n | \r / " , $headers );
list ( $protocol , $code , $text ) = explode ( ' ' , trim ( array_shift ( $headers )), 3 );
2004-01-07 19:52:10 +00:00
$result -> headers = array ();
// Parse headers.
2004-06-21 20:14:41 +00:00
while ( $line = trim ( array_shift ( $headers ))) {
2004-01-07 19:52:10 +00:00
list ( $header , $value ) = explode ( ':' , $line , 2 );
$result -> headers [ $header ] = trim ( $value );
}
$responses = array (
100 => 'Continue' , 101 => 'Switching Protocols' ,
200 => 'OK' , 201 => 'Created' , 202 => 'Accepted' , 203 => 'Non-Authoritative Information' , 204 => 'No Content' , 205 => 'Reset Content' , 206 => 'Partial Content' ,
300 => 'Multiple Choices' , 301 => 'Moved Permanently' , 302 => 'Found' , 303 => 'See Other' , 304 => 'Not Modified' , 305 => 'Use Proxy' , 307 => 'Temporary Redirect' ,
400 => 'Bad Request' , 401 => 'Unauthorized' , 402 => 'Payment Required' , 403 => 'Forbidden' , 404 => 'Not Found' , 405 => 'Method Not Allowed' , 406 => 'Not Acceptable' , 407 => 'Proxy Authentication Required' , 408 => 'Request Time-out' , 409 => 'Conflict' , 410 => 'Gone' , 411 => 'Length Required' , 412 => 'Precondition Failed' , 413 => 'Request Entity Too Large' , 414 => 'Request-URI Too Large' , 415 => 'Unsupported Media Type' , 416 => 'Requested range not satisfiable' , 417 => 'Expectation Failed' ,
500 => 'Internal Server Error' , 501 => 'Not Implemented' , 502 => 'Bad Gateway' , 503 => 'Service Unavailable' , 504 => 'Gateway Time-out' , 505 => 'HTTP Version not supported'
);
// RFC 2616 states that all unknown HTTP codes must be treated the same as
// the base code in their class:
if ( ! isset ( $responses [ $code ])) {
$code = floor ( $code / 100 ) * 100 ;
}
switch ( $code ) {
case 200 : // OK
case 304 : // Not modified
break ;
case 301 : // Moved permanently
case 302 : // Moved temporarily
case 307 : // Moved temporarily
$location = $result -> headers [ 'Location' ];
if ( $retry ) {
$result = drupal_http_request ( $result -> headers [ 'Location' ], $headers , $method , $data , -- $retry );
$result -> redirect_code = $result -> code ;
}
$result -> redirect_url = $location ;
break ;
default :
$result -> error = $text ;
}
$result -> code = $code ;
return $result ;
}
2004-01-06 19:52:14 +00:00
/* @} */
2003-12-16 21:06:34 +00:00
2004-07-13 07:21:14 +00:00
/**
* Log errors in the database rather than displaying them to the user .
*/
2001-12-01 15:20:48 +00:00
function error_handler ( $errno , $message , $filename , $line , $variables ) {
2004-07-13 07:21:14 +00:00
$types = array ( 1 => 'error' , 2 => 'warning' , 4 => 'parse error' , 8 => 'notice' , 16 => 'core error' , 32 => 'core warning' , 64 => 'compile error' , 128 => 'compile warning' , 256 => 'user error' , 512 => 'user warning' , 1024 => 'user notice' );
$entry = $types [ $errno ] . ': ' . $message . ' in ' . $filename . ' on line ' . $line . '.' ;
2003-04-21 12:36:09 +00:00
if ( $errno & E_ALL ^ E_NOTICE ) {
2004-06-02 19:01:40 +00:00
watchdog ( 'error' , t ( '%error: %message in %file on line %line.' , array ( '%error' => $types [ $errno ], '%message' => $message , '%file' => $filename , '%line' => $line )));
2003-12-13 14:59:55 +00:00
if ( error_reporting ()) {
2004-07-13 07:21:14 +00:00
print '<pre>' . $entry . '</pre>' ;
2003-12-13 14:59:55 +00:00
}
2001-12-01 15:20:48 +00:00
}
}
2003-12-13 14:59:55 +00:00
function _fix_gpc_magic ( & $item , $key ) {
if ( is_array ( $item )) {
2003-12-19 10:52:37 +00:00
array_walk ( $item , '_fix_gpc_magic' );
}
else {
2003-12-19 13:44:08 +00:00
$item = stripslashes ( $item );
2002-12-26 12:16:09 +00:00
}
}
2004-07-13 07:21:14 +00:00
/**
* Correct double - escaping problems caused by " magic quotes " in some PHP
* installations .
*/
2003-10-31 19:34:03 +00:00
function fix_gpc_magic () {
static $fixed = false ;
2004-07-13 07:21:14 +00:00
if ( ! $fixed && ini_get ( 'magic_quotes_gpc' )) {
2003-12-13 14:59:55 +00:00
array_walk ( $_GET , '_fix_gpc_magic' );
array_walk ( $_POST , '_fix_gpc_magic' );
array_walk ( $_COOKIE , '_fix_gpc_magic' );
array_walk ( $_REQUEST , '_fix_gpc_magic' );
$fixed = true ;
}
2003-10-31 19:34:03 +00:00
}
2004-01-06 19:52:14 +00:00
/**
* @ name Conversion
*
* Converts data structures to a different type .
* @ {
*/
2004-07-13 07:21:14 +00:00
/**
* Convert an associative array to an anonymous object .
*/
2003-12-13 14:59:55 +00:00
function array2object ( $array ) {
if ( is_array ( $array )) {
foreach ( $array as $key => $value ) {
2001-12-30 16:16:38 +00:00
$object -> $key = $value ;
}
}
else {
2003-12-13 14:59:55 +00:00
$object = $array ;
2001-12-30 16:16:38 +00:00
}
return $object ;
}
2004-07-13 07:21:14 +00:00
/**
* Convert an object to an associative array .
*/
2003-12-13 14:59:55 +00:00
function object2array ( $object ) {
if ( is_object ( $object )) {
foreach ( $object as $key => $value ) {
2001-12-30 16:16:38 +00:00
$array [ $key ] = $value ;
}
}
else {
2003-12-13 14:59:55 +00:00
$array = $object ;
2001-12-30 16:16:38 +00:00
}
return $array ;
}
2004-01-06 19:52:14 +00:00
/* @} */
2001-12-30 16:16:38 +00:00
2004-01-06 19:52:14 +00:00
/**
* @ name Messages
*
* Frequently used messages .
* @ {
*/
2004-07-13 07:21:14 +00:00
/**
* Return a string with an " access denied " message .
*
* Always consider whether to use drupal_access_denied () instead to return a
* proper ( and customizable ) 403 error .
*/
2001-12-01 15:20:48 +00:00
function message_access () {
2004-07-13 07:21:14 +00:00
return t ( 'You are not authorized to access this page.' );
2001-12-01 15:20:48 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Return a string with a " not applicable " message .
*/
2001-12-01 15:20:48 +00:00
function message_na () {
2004-07-13 07:21:14 +00:00
return t ( 'n/a' );
2001-12-01 15:20:48 +00:00
}
2004-01-06 19:52:14 +00:00
/* @} */
2001-12-01 15:20:48 +00:00
2004-07-13 07:21:14 +00:00
/**
* Initialize the localization system .
*/
2001-12-27 15:27:44 +00:00
function locale_init () {
global $languages , $user ;
2003-03-04 15:10:37 +00:00
if ( $user -> uid && $languages [ $user -> language ]) {
return $user -> language ;
}
else {
return key ( $languages );
}
2001-12-27 15:27:44 +00:00
}
2004-01-06 19:52:14 +00:00
/**
2004-07-13 07:21:14 +00:00
* Translate strings to the current locale .
2004-01-06 19:52:14 +00:00
*
2004-01-11 20:31:26 +00:00
* When using t (), try to put entire sentences and strings in one t () call .
* This makes it easier for translators . We are unafraid of HTML markup within
* translation strings if necessary . The suggested syntax for a link embedded
* within a translation string is for example :
2004-07-13 07:21:14 +00:00
* @ verbatim
* $msg = t ( ' You must log in below or < a href = " %url " > create a new
* account </ a > before viewing the next page . ', array(' % url '
* => url ( 'user/register' )));
* @ endverbatim
2004-01-11 20:31:26 +00:00
* We suggest the same syntax for links to other sites . This makes it easy to
* change link URLs if needed ( which happens often ) without requiring updates
* to translations .
2004-01-06 19:52:14 +00:00
*
2004-07-13 07:21:14 +00:00
* @ param $string
* A string containing the english string to translate .
* @ param $args
* An associative array of replacements to make after translation . Incidences
* of any key in this array are replaces with the corresponding value .
* @ return
* The translated string .
2004-01-06 19:52:14 +00:00
*/
2002-04-20 11:52:50 +00:00
function t ( $string , $args = 0 ) {
2001-12-27 15:27:44 +00:00
global $languages ;
2002-04-24 20:55:20 +00:00
2004-07-13 07:21:14 +00:00
$string = ( $languages && module_exist ( 'locale' ) ? locale ( $string ) : $string );
2002-04-24 20:55:20 +00:00
2002-04-20 11:52:50 +00:00
if ( ! $args ) {
return $string ;
2002-04-22 09:05:36 +00:00
}
else {
2002-04-20 11:52:50 +00:00
return strtr ( $string , $args );
}
2001-12-27 15:27:44 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Encode special characters in a string for display as HTML .
*
* Note that we 'd like to use htmlspecialchars($input, $quotes, ' utf - 8 ' )
* as outlined in the PHP manual , but we can 't because there' s a bug in
* PHP < 4.3 that makes it mess up multibyte charsets if we specify the
* charset . This will be changed later once we make PHP 4.3 a requirement .
*/
2003-06-12 17:24:06 +00:00
function drupal_specialchars ( $input , $quotes = ENT_NOQUOTES ) {
2003-06-19 17:26:27 +00:00
return htmlspecialchars ( $input , $quotes );
2003-06-05 18:09:39 +00:00
}
2004-01-06 19:52:14 +00:00
/**
* @ name Validation
*
* Functions to validate user input .
2004-02-08 17:12:44 +00:00
* @ {
2004-01-06 19:52:14 +00:00
*/
2003-03-28 10:55:27 +00:00
/**
2004-07-13 07:21:14 +00:00
* Verify the syntax of the given e - mail address .
*
* Empty e - mail addresses are allowed . See RFC 2822 for details .
2003-03-28 10:55:27 +00:00
*
2004-07-13 07:21:14 +00:00
* @ param $mail
* A string containing an email address .
2004-01-07 19:52:10 +00:00
* @ return
2004-07-13 07:21:14 +00:00
* TRUE if the address is in a valid format .
2003-03-28 10:55:27 +00:00
*/
2003-04-13 13:42:51 +00:00
function valid_email_address ( $mail ) {
2003-03-28 10:55:27 +00:00
$user = '[a-zA-Z0-9_\-\.\+\^!#\$%&*+\/\=\?\`\|\{\}~\']+' ;
2004-05-24 18:09:28 +00:00
$domain = '(?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.?)+' ;
2003-03-28 10:55:27 +00:00
$ipv4 = '[0-9]{1,3}(\.[0-9]{1,3}){3}' ;
$ipv6 = '[0-9a-fA-F]{1,4}(\:[0-9a-fA-F]{1,4}){7}' ;
2003-12-13 14:59:55 +00:00
return preg_match ( " /^ $user @( $domain |( \ [( $ipv4 | $ipv6 ) \ ])) $ / " , $mail );
2003-03-28 10:55:27 +00:00
}
2003-07-16 20:14:26 +00:00
/**
* Verify the syntax of the given URL .
*
2004-04-12 08:27:57 +00:00
* @ param $url
2004-07-13 07:21:14 +00:00
* The URL to verify .
2004-04-12 08:27:57 +00:00
* @ param $absolute
2004-07-13 07:21:14 +00:00
* Whether the URL is absolute ( beginning with a scheme such as http ) .
2004-04-12 08:27:57 +00:00
* @ return
2004-07-13 07:21:14 +00:00
* TRUE if the URL is in a valid format .
2003-07-16 20:14:26 +00:00
*/
2004-04-12 08:27:57 +00:00
function valid_url ( $url , $absolute = FALSE ) {
2004-03-21 10:28:10 +00:00
if ( $absolute ) {
2004-03-27 09:32:12 +00:00
return preg_match ( " /^(http|https|ftp): \ / \ /[a-z0-9 \ /:_ \ -_ \ . \ ?,~=#&]+ $ /i " , $url );
2004-03-21 10:28:10 +00:00
}
else {
2004-03-27 09:32:12 +00:00
return preg_match ( " /^[a-z0-9 \ /:_ \ -_ \ .,]+ $ /i " , $url );
2004-03-21 10:28:10 +00:00
}
2003-07-16 20:14:26 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Validate data input by a user .
*
* Ensures that user data cannot be used to perform attacks on the site .
*
* @ param $data
* The input to check .
* @ return
* TRUE if the input data is acceptable .
*/
2004-01-06 19:52:14 +00:00
function valid_input_data ( $data ) {
if ( is_array ( $data ) || is_object ( $data )) {
2004-07-13 07:21:14 +00:00
// Form data can contain a number of nested arrays.
2004-01-06 19:52:14 +00:00
foreach ( $data as $key => $value ) {
2004-01-17 23:19:02 +00:00
if ( ! valid_input_data ( $key ) || ! valid_input_data ( $value )) {
2004-07-13 07:21:14 +00:00
return FALSE ;
2004-01-06 19:52:14 +00:00
}
}
}
else {
2004-07-13 07:21:14 +00:00
// Detect dangerous input data.
2004-01-06 19:52:14 +00:00
2004-07-13 07:21:14 +00:00
// Check strings:
$match = preg_match ( '/\Wjavascript\s*:/i' , $data );
$match += preg_match ( '/\Wexpression\s*\(/i' , $data );
$match += preg_match ( '/\Walert\s*\(/i' , $data );
2004-01-06 19:52:14 +00:00
2004-07-13 07:21:14 +00:00
// Check attributes:
2004-01-06 19:52:14 +00:00
$match += preg_match ( " / \ W(dynsrc|datasrc|data|lowsrc|on[a-z]+) \ s*=[^>]+?>/i " , $data );
2004-07-13 07:21:14 +00:00
// Check tags:
2004-01-06 19:52:14 +00:00
$match += preg_match ( " /< \ s*(applet|script|object|style|embed|form|blink|meta|html|frame|iframe|layer|ilayer|head|frameset|xml)/i " , $data );
if ( $match ) {
2004-06-02 19:01:40 +00:00
watchdog ( 'warning' , t ( 'terminated request because of suspicious input data: %data' , array ( '%data' => drupal_specialchars ( $data ))));
2004-07-13 07:21:14 +00:00
return FALSE ;
2004-01-06 19:52:14 +00:00
}
}
2004-07-13 07:21:14 +00:00
return TRUE ;
2004-01-06 19:52:14 +00:00
}
/* @} */
/**
* @ defgroup search Search interface
* @ {
*/
2004-07-13 07:21:14 +00:00
2002-03-05 20:15:17 +00:00
/**
* Format a single result entry of a search query :
*
2003-12-08 06:32:19 +00:00
* @ param $item a single search result as returned by < i > module </ i > _search of
2004-07-13 07:21:14 +00:00
* type array ( 'count' => ... , 'link' => ... , 'title' => ... , 'user' => ... ,
* 'date' => ... , 'keywords' => ... )
2003-12-08 06:32:19 +00:00
* @ param $type module type of this item
2002-03-05 20:15:17 +00:00
*/
2001-12-27 15:27:44 +00:00
function search_item ( $item , $type ) {
2002-04-27 13:19:37 +00:00
/*
2004-07-13 07:21:14 +00:00
** Modules may implement hook_search_item () hook in order to overwrite
2002-04-27 13:19:37 +00:00
** the default function to display search results .
*/
2004-07-13 07:21:14 +00:00
if ( module_hook ( $type , 'search_item' )) {
$output = module_invoke ( $type , 'search_item' , $item );
2002-04-27 13:19:37 +00:00
}
else {
2004-07-13 07:21:14 +00:00
$output = ' <dt class="title"><a href="' . $item [ 'link' ] . '">' . $item [ 'title' ] . '</a></dt>' ;
$output .= ' <dd class="small">' . t ( $type ) . ( $item [ 'user' ] ? ' - ' . $item [ 'user' ] : '' ) . '' . ( $item [ 'date' ] ? ' - ' . format_date ( $item [ 'date' ], 'small' ) : '' ) . '</dd>' ;
2002-04-27 13:19:37 +00:00
}
2001-12-27 15:27:44 +00:00
return $output ;
}
2002-03-05 20:15:17 +00:00
/**
* Render a generic search form .
*
* " Generic " means " universal usable " - that is , usable not only from
2004-06-21 20:05:37 +00:00
* 'site.com/search' , but also as a simple search box ( without " Restrict search
2003-12-08 06:32:19 +00:00
* to " , help text, etc) from theme's header etc. This means: provide options to
* only conditionally render certain parts of this form .
2002-03-05 20:15:17 +00:00
*
2003-12-08 06:32:19 +00:00
* @ param $action Form action . Defaults to 'site.com/search' .
* @ param $keys string containing keywords for the search .
* @ param $options != 0 : Render additional form fields / text ( " Restrict search
* to " , help text, etc).
2002-03-05 20:15:17 +00:00
*/
2003-06-30 19:18:47 +00:00
function search_form ( $action = NULL , $keys = NULL , $options = NULL ) {
2004-01-02 12:15:37 +00:00
$edit = $_POST [ 'edit' ];
2001-12-27 15:27:44 +00:00
if ( ! $action ) {
2004-07-13 07:21:14 +00:00
$action = url ( 'search' );
2001-12-27 15:27:44 +00:00
}
2004-07-13 07:21:14 +00:00
$output = ' <div class="search-form"><br /><input type="text" class="form-text" size="50" value="' . check_form ( $keys ) . '" name="keys" />' ;
$output .= ' <input type="submit" class="form-submit" value="' . t ( 'Search' ) . " \" /> \n " ;
2001-12-27 15:27:44 +00:00
2003-12-13 14:59:55 +00:00
if ( $options ) {
2004-07-13 07:21:14 +00:00
$output .= '<br />' ;
$output .= t ( 'Restrict search to' ) . ': ' ;
2001-12-27 15:27:44 +00:00
foreach ( module_list () as $name ) {
2004-07-13 07:21:14 +00:00
if ( module_hook ( $name , 'search' )) {
$output .= ' <input type="checkbox" name="edit[type][' . $name . ']" ' . ( $edit [ 'type' ][ $name ] ? ' checked="checked"' : '' ) . ' /> ' . t ( $name );
2001-12-27 15:27:44 +00:00
}
}
2004-07-13 07:21:14 +00:00
$output .= '</div>' ;
2001-12-27 15:27:44 +00:00
}
2004-07-13 07:21:14 +00:00
return form ( $output , 'post' , $action );
2001-12-27 15:27:44 +00:00
}
/*
2002-03-05 20:15:17 +00:00
* Collect the search results :
*/
2003-06-25 22:10:54 +00:00
function search_data ( $keys = NULL ) {
2004-07-13 07:21:14 +00:00
$edit = $_POST [ 'edit' ];
2004-04-12 08:27:57 +00:00
$output = '' ;
2001-12-27 15:27:44 +00:00
2003-01-09 20:06:00 +00:00
if ( isset ( $keys )) {
2001-12-27 15:27:44 +00:00
foreach ( module_list () as $name ) {
2004-07-13 07:21:14 +00:00
if ( module_hook ( $name , 'search' ) && ( ! $edit [ 'type' ] || $edit [ 'type' ][ $name ])) {
list ( $title , $results ) = module_invoke ( $name , 'search' , $keys );
2004-02-01 19:07:36 +00:00
if ( $results ) {
2004-07-13 07:21:14 +00:00
$output .= '<h2>' . $title . '</h2>' ;
$output .= '<dl class="search-results">' ;
2004-02-01 19:07:36 +00:00
foreach ( $results as $entry ) {
$output .= search_item ( $entry , $name );
}
2004-07-13 07:21:14 +00:00
$output .= '</dl>' ;
2001-12-27 15:27:44 +00:00
}
}
}
}
return $output ;
}
2002-03-05 20:15:17 +00:00
/**
* Display the search form and the resulting data .
*
2003-12-08 06:32:19 +00:00
* @ param $type If set , search only nodes of this type . Otherwise , search all
* types .
* @ param $action Form action . Defaults to 'site.com/search' .
* @ param $keys Query string . Defaults to global $keys .
* @ param $options != 0 : Render additional form fields / text ( " Restrict search
* to " , help text, etc).
2002-03-05 20:15:17 +00:00
*/
2003-06-30 19:18:47 +00:00
function search_type ( $type , $action = NULL , $keys = NULL , $options = NULL ) {
2004-07-13 07:21:14 +00:00
$_POST [ 'edit' ][ 'type' ][ $type ] = 'on' ;
2001-12-27 15:27:44 +00:00
2004-07-13 07:21:14 +00:00
return search_form ( $action , $keys , $options ) . '<br />' . search_data ( $keys );
2001-12-27 15:27:44 +00:00
}
2004-01-06 19:52:14 +00:00
/* @} */
2003-06-06 21:08:35 +00:00
2001-12-01 15:20:48 +00:00
function check_form ( $text ) {
2003-06-23 07:24:56 +00:00
return drupal_specialchars ( $text , ENT_QUOTES );
2001-12-01 15:20:48 +00:00
}
2003-10-07 10:22:33 +00:00
function check_file ( $filename ) {
return is_uploaded_file ( $filename );
2001-12-01 15:20:48 +00:00
}
2004-02-08 17:12:44 +00:00
/**
* @ name Formatting
*
* Functions to format numbers , strings , dates , etc .
* @ {
*/
2004-07-13 07:21:14 +00:00
/**
* Formats an RSS channel .
*
* Arbitrary elements may be added using the $args associative array .
*/
function format_rss_channel ( $title , $link , $description , $items , $language = 'en' , $args = array ()) {
2002-04-27 13:19:37 +00:00
// arbitrary elements may be added using the $args associative array
2003-12-13 14:59:55 +00:00
$output = " <channel> \n " ;
2004-07-13 07:21:14 +00:00
$output .= ' <title>' . drupal_specialchars ( strip_tags ( $title )) . " </title> \n " ;
$output .= ' <link>' . drupal_specialchars ( strip_tags ( $link )) . " </link> \n " ;
$output .= ' <description>' . drupal_specialchars ( strip_tags ( $description )) . " </description> \n " ;
$output .= ' <language>' . drupal_specialchars ( strip_tags ( $language )) . " </language> \n " ;
2002-04-27 13:19:37 +00:00
foreach ( $args as $key => $value ) {
2004-07-13 07:21:14 +00:00
$output .= ' <' . $key . '>' . drupal_specialchars ( strip_tags ( $value )) . " </ $key > \n " ;
2002-04-27 13:19:37 +00:00
}
2001-12-01 15:20:48 +00:00
$output .= $items ;
$output .= " </channel> \n " ;
return $output ;
}
2004-07-13 07:21:14 +00:00
/**
* Format a single RSS item .
*
* Arbitrary elements may be added using the $args associative array .
*/
2002-04-27 13:19:37 +00:00
function format_rss_item ( $title , $link , $description , $args = array ()) {
2003-12-13 14:59:55 +00:00
$output = " <item> \n " ;
2004-07-13 07:21:14 +00:00
$output .= ' <title>' . drupal_specialchars ( strip_tags ( $title )) . " </title> \n " ;
$output .= ' <link>' . drupal_specialchars ( strip_tags ( $link )) . " </link> \n " ;
$output .= ' <description>' . drupal_specialchars ( check_output ( $description )) . " </description> \n " ;
2002-04-27 13:19:37 +00:00
foreach ( $args as $key => $value ) {
2004-07-13 07:21:14 +00:00
$output .= ' <' . $key . '>' . drupal_specialchars ( strip_tags ( $value )) . " </ $key > \n " ;
2002-04-27 13:19:37 +00:00
}
2001-12-01 15:20:48 +00:00
$output .= " </item> \n " ;
return $output ;
}
2003-01-21 22:44:25 +00:00
/**
2004-07-13 07:21:14 +00:00
* Format a string containing a count of items .
2003-01-21 22:44:25 +00:00
*
2004-07-13 07:21:14 +00:00
* This function ensures that the string is pluralized correctly . Since t () is
* called by this function , make sure not to pass already - localized strings to it .
*
* @ param $count
* The item count to display .
* @ param $singular
* The string for the singular case . Please make sure it is clear this is
* singular , to ease translation ( e . g . use " 1 new comment " instead of " 1 new " ) .
* @ param $plural
* The string for the plural case . Please make sure it is clear this is plural ,
* to ease translation . Use % count in place of the item count , as in " %count
* new comments " .
* @ return
* A translated string .
2003-01-21 22:44:25 +00:00
*/
2001-12-01 15:20:48 +00:00
function format_plural ( $count , $singular , $plural ) {
2004-07-13 07:21:14 +00:00
return t ( $count == 1 ? $singular : $plural , array ( '%count' => $count ));
2001-12-01 15:20:48 +00:00
}
2004-02-08 17:12:44 +00:00
/**
2004-07-13 07:21:14 +00:00
* Generate a string representation for the given byte count .
2004-02-08 17:12:44 +00:00
*
2004-07-13 07:21:14 +00:00
* @ param $size
* The size in bytes .
* @ return
* A translated string representation of the size .
2004-02-08 17:12:44 +00:00
*/
2001-12-01 15:20:48 +00:00
function format_size ( $size ) {
2004-07-13 07:21:14 +00:00
$suffix = t ( 'bytes' );
2001-12-01 15:20:48 +00:00
if ( $size > 1024 ) {
$size = round ( $size / 1024 , 2 );
2004-07-13 07:21:14 +00:00
$suffix = t ( 'KB' );
2001-12-01 15:20:48 +00:00
}
if ( $size > 1024 ) {
$size = round ( $size / 1024 , 2 );
2004-07-13 07:21:14 +00:00
$suffix = t ( 'MB' );
2001-12-01 15:20:48 +00:00
}
2004-07-13 07:21:14 +00:00
return t ( '%size %suffix' , array ( '%size' => $size , '%suffix' => $suffix ));
2001-12-01 15:20:48 +00:00
}
2004-02-08 17:12:44 +00:00
/**
2004-07-13 07:21:14 +00:00
* Format a time interval with the requested granularity .
2004-02-08 17:12:44 +00:00
*
2004-07-13 07:21:14 +00:00
* @ param $timestamp
* The length of the interval in seconds .
* @ param $granularity
* How many different units to display in the string .
* @ return
* A translated string representation of the interval .
2004-02-08 17:12:44 +00:00
*/
2004-01-21 06:40:57 +00:00
function format_interval ( $timestamp , $granularity = 2 ) {
2004-07-13 07:21:14 +00:00
$units = array ( '1 year|%count years' => 31536000 , '1 week|%count weeks' => 604800 , '1 day|%count days' => 86400 , '1 hour|%count hours' => 3600 , '1 min|%count min' => 60 , '1 sec|%count sec' => 1 );
2004-04-12 08:27:57 +00:00
$output = '' ;
2003-12-24 12:40:28 +00:00
foreach ( $units as $key => $value ) {
2004-07-13 07:21:14 +00:00
$key = explode ( '|' , $key );
2001-12-01 15:20:48 +00:00
if ( $timestamp >= $value ) {
2004-07-13 07:21:14 +00:00
$output .= ( $output ? ' ' : '' ) . format_plural ( floor ( $timestamp / $value ), $key [ 0 ], $key [ 1 ]);
2001-12-01 15:20:48 +00:00
$timestamp %= $value ;
2004-01-21 06:40:57 +00:00
$granularity -- ;
}
if ( $granularity == 0 ) {
break ;
2001-12-01 15:20:48 +00:00
}
}
2004-07-13 07:21:14 +00:00
return $output ? $output : t ( '0 sec' );
2001-12-01 15:20:48 +00:00
}
2004-02-08 17:12:44 +00:00
/**
2004-07-13 07:21:14 +00:00
* Format a date with the given configured format or a custom format string .
*
2004-02-08 17:12:44 +00:00
* Drupal allows administrators to select formatting strings for 'small' ,
* 'medium' and 'large' date formats . This function can handle these formats ,
* as well as any custom format .
*
2004-07-13 07:21:14 +00:00
* @ param $timestamp
* The exact date to format , as a UNIX timestamp .
* @ param $type
* The format to use . Can be " small " , " medium " or " large " for the preconfigured
* date formats . If " custom " is specified , then $format is required as well .
* @ param $format
* A PHP date format string as required by date () .
* @ param $timezone
* Time zone offset in seconds ; if omitted , the user ' s time zone is used .
* @ return
* A translated date string in the requested format .
2004-02-08 17:12:44 +00:00
*/
2004-02-08 21:42:59 +00:00
function format_date ( $timestamp , $type = 'medium' , $format = '' , $timezone = NULL ) {
if ( $timezone === NULL ) {
global $user ;
$timezone = $user -> uid ? $user -> timezone : variable_get ( 'date_default_timezone' , 0 );
}
2001-12-01 15:20:48 +00:00
2004-02-08 21:42:59 +00:00
$timestamp += $timezone ;
2001-12-01 15:20:48 +00:00
switch ( $type ) {
2004-02-08 21:42:59 +00:00
case 'small' :
$format = variable_get ( 'date_format_short' , 'm/d/Y - H:i' );
2001-12-01 15:20:48 +00:00
break ;
2004-02-08 21:42:59 +00:00
case 'large' :
$format = variable_get ( 'date_format_long' , 'l, F j, Y - H:i' );
2001-12-01 15:20:48 +00:00
break ;
2004-02-08 21:42:59 +00:00
case 'custom' :
2003-09-29 18:20:38 +00:00
// No change to format
2001-12-01 15:20:48 +00:00
break ;
2004-02-08 21:42:59 +00:00
case 'medium' :
2001-12-01 15:20:48 +00:00
default :
2004-02-08 21:42:59 +00:00
$format = variable_get ( 'date_format_medium' , 'D, m/d/Y - H:i' );
2003-09-29 18:20:38 +00:00
}
2004-02-08 21:42:59 +00:00
$max = strlen ( $format );
2004-04-12 08:27:57 +00:00
$date = '' ;
2004-07-02 18:46:42 +00:00
for ( $i = 0 ; $i < $max ; $i ++ ) {
$c = $format { $i };
2004-02-08 21:42:59 +00:00
if ( strpos ( 'AaDFlM' , $c )) {
2004-02-21 14:08:09 +00:00
$date .= t ( gmdate ( $c , $timestamp ));
2004-02-08 21:42:59 +00:00
}
else if ( strpos ( 'BdgGhHiIjLmnsStTUwWYyz' , $c )) {
$date .= gmdate ( $c , $timestamp );
}
else if ( $c == 'r' ) {
$date .= format_date ( $timestamp - $timezone , 'custom' , 'D, d M Y H:i:s O' , $timezone );
2003-09-29 18:20:38 +00:00
}
2004-02-08 21:42:59 +00:00
else if ( $c == 'O' ) {
$date .= sprintf ( '%s%02d%02d' , ( $timezone < 0 ? '-' : '+' ), abs ( $timezone / 3600 ), abs ( $timezone % 3600 ) / 60 );
}
else if ( $c == 'Z' ) {
$date .= $timezone ;
2003-09-29 18:20:38 +00:00
}
else {
2004-02-08 21:42:59 +00:00
$date .= $c ;
2003-09-29 18:20:38 +00:00
}
2001-12-01 15:20:48 +00:00
}
2004-02-08 21:42:59 +00:00
2001-12-01 15:20:48 +00:00
return $date ;
}
2004-02-08 17:12:44 +00:00
/**
2004-07-13 07:21:14 +00:00
* Format a username .
2004-02-08 17:12:44 +00:00
*
2004-07-13 07:21:14 +00:00
* @ param $object
* The user object to format , usually returned from user_load () .
* @ return
* A string containing an HTML link to the user ' s page if the passed object
* suggests that this is a site user . Otherwise , only the username is returned .
2004-02-08 17:12:44 +00:00
*/
2001-12-01 15:20:48 +00:00
function format_name ( $object ) {
if ( $object -> uid && $object -> name ) {
2004-07-13 07:21:14 +00:00
// Shorten the name when it is too long or it will break many tables.
2003-08-22 21:35:25 +00:00
if ( strlen ( $object -> name ) > 20 ) {
2004-07-13 07:21:14 +00:00
$name = truncate_utf8 ( $object -> name , 15 ) . '...' ;
2003-08-22 21:35:25 +00:00
}
else {
$name = $object -> name ;
}
2004-07-13 07:21:14 +00:00
$output = l ( $name , 'user/' . $object -> uid , array ( 'title' => t ( 'View user profile.' )));
2001-12-01 15:20:48 +00:00
}
2003-02-02 10:13:13 +00:00
else if ( $object -> name ) {
2004-07-13 07:21:14 +00:00
// Sometimes modules display content composed by people who are
// not registered members of the site (e.g. mailing list or news
// aggregator modules). This clause enables modules to display
// the true author of the content.
2004-05-18 18:41:46 +00:00
if ( $object -> homepage ) {
2004-07-13 07:21:14 +00:00
$output = '<a href="' . $object -> homepage . '">' . $object -> name . '</a>' ;
2004-05-18 18:41:46 +00:00
}
else {
$output = $object -> name ;
}
$output .= ' (' . t ( 'not verified' ) . ')' ;
2003-02-02 10:13:13 +00:00
}
2001-12-01 15:20:48 +00:00
else {
2004-07-13 07:21:14 +00:00
$output = t ( variable_get ( 'anonymous' , 'Anonymous' ));
2001-12-01 15:20:48 +00:00
}
2001-12-05 18:54:14 +00:00
return $output ;
2001-12-01 15:20:48 +00:00
}
2004-02-08 17:12:44 +00:00
/* @} */
2001-12-01 15:20:48 +00:00
2004-01-06 19:52:14 +00:00
/**
2004-07-13 07:21:14 +00:00
* @ defgroup form Form generation
2004-01-06 19:52:14 +00:00
* @ {
*/
2004-07-13 07:21:14 +00:00
/**
* Generate a form from a set of form elements .
*
* @ param $form
* An HTML string containing one or more form elements .
* @ param $method
* The query method to use ( " post " or " get " ) .
* @ param $action
* The URL to send the form contents to , if not the current page .
* @ param $attributes
* An associative array of attributes to add to the form tag .
* @ result
* An HTML string with the contents of $form wrapped in a form tag .
*/
function form ( $form , $method = 'post' , $action = NULL , $attributes = NULL ) {
2003-05-19 18:26:49 +00:00
if ( ! $action ) {
2003-06-03 18:04:47 +00:00
$action = request_uri ();
2003-05-19 18:26:49 +00:00
}
2004-07-13 07:21:14 +00:00
return '<form action="' . $action . '" method="' . $method . '"' . drupal_attributes ( $attributes ) . " > \n " . $form . " \n </form> \n " ;
2001-12-01 15:20:48 +00:00
}
2004-05-31 09:40:56 +00:00
/**
2004-07-13 07:21:14 +00:00
* File an error against the form element with the specified name .
2004-05-31 09:40:56 +00:00
*/
function form_set_error ( $name , $message ) {
$GLOBALS [ 'form' ][ $name ] = $message ;
drupal_set_message ( $message , 'error' );
}
/**
2004-07-04 16:50:02 +00:00
* Return an associative array of all errors .
2004-05-31 09:40:56 +00:00
*/
2004-07-04 16:50:02 +00:00
function form_get_errors () {
2004-07-04 06:19:41 +00:00
if ( array_key_exists ( 'form' , $GLOBALS )) {
return $GLOBALS [ 'form' ];
}
2004-05-31 09:40:56 +00:00
}
/**
* Return the error message filed against the form with the specified name .
*/
function _form_get_error ( $name ) {
2004-07-02 18:46:42 +00:00
if ( array_key_exists ( 'form' , $GLOBALS )) {
return $GLOBALS [ 'form' ][ $name ];
}
2004-05-31 09:40:56 +00:00
}
function _form_get_class ( $name , $required , $error ) {
return $name . ( $required ? ' required' : '' ) . ( $error ? ' error' : '' );
}
2004-07-13 07:21:14 +00:00
/**
* Format a general form item .
*
* @ param $title
* The label for the form item .
* @ param $value
* The contents of the form item .
* @ param $description
* Explanatory text to display after the form item .
* @ param $id
* A unique identifier for the form item .
* @ param $required
* Whether the user must fill in this form element before submitting the form .
* @ param $error
* An error message to display alongside the form element .
* @ return
* A themed HTML string representing the form item .
*/
2004-05-31 09:40:56 +00:00
function form_item ( $title , $value , $description = NULL , $id = NULL , $required = FALSE , $error = FALSE ) {
2004-07-08 11:31:12 +00:00
return theme ( 'form_element' , $title , $value , $description , $id , $required , $error );
2001-12-01 15:20:48 +00:00
}
2003-11-17 19:16:55 +00:00
2004-07-13 07:21:14 +00:00
/**
* Format a group of form items .
*
* @ param $legend
* The label for the form item group .
* @ param $group
* The form items within the group , as an HTML string .
* @ param $description
* Explanatory text to display after the form item group .
* @ return
* A themed HTML string representing the form item group .
*/
2003-12-22 14:45:00 +00:00
function form_group ( $legend , $group , $description = NULL ) {
2004-07-13 07:21:14 +00:00
return '<fieldset>' . ( $legend ? '<legend>' . $legend . '</legend>' : '' ) . $group . ( $description ? '<div class="description">' . $description . '</div>' : '' ) . " </fieldset> \n " ;
2003-11-06 18:27:58 +00:00
}
2001-12-01 15:20:48 +00:00
2004-07-13 07:21:14 +00:00
/**
* Format a radio button .
*
* @ param $title
* The label for the radio button .
* @ param $name
* The internal name used to refer to the button .
* @ param $value
* The value that the form element takes on when selected .
* @ param $checked
* Whether the button will be initially selected when the page is rendered .
* @ param $description
* Explanatory text to display after the form item .
* @ param $attributes
* An associative array of HTML attributes to add to the button .
* @ param $required
* Whether the user must select this radio button before submitting the form .
* @ return
* A themed HTML string representing the radio button .
*/
function form_radio ( $title , $name , $value = 1 , $checked = FALSE , $description = NULL , $attributes = NULL , $required = FALSE ) {
$element = '<input type="radio" class="' . _form_get_class ( 'form-radio' , $required , _form_get_error ( $name )) . '" name="edit[' . $name . ']" value="' . $value . '"' . ( $checked ? ' checked="checked"' : '' ) . drupal_attributes ( $attributes ) . ' />' ;
2004-02-24 20:22:45 +00:00
if ( ! is_null ( $title )) {
2004-07-13 07:21:14 +00:00
$element = '<label class="option">' . $element . ' ' . $title . '</label>' ;
2004-02-24 20:22:45 +00:00
}
2004-07-08 11:31:12 +00:00
return theme ( 'form_element' , NULL , $element , $description , $name , $required , _form_get_error ( $name ));
2003-12-24 12:40:28 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Format a set of radio buttons .
*
* @ param $title
* The label for the radio buttons as a group .
* @ param $name
* The internal name used to refer to the buttons .
* @ param $value
* The currently selected radio button ' s key .
* @ param $options
* An associative array of buttons to display . The keys in this array are
* button values , while the values are the labels to display for each button .
* @ param $description
* Explanatory text to display after the form item .
* @ param $required
* Whether the user must select a radio button before submitting the form .
* @ param $attributes
* An associative array of HTML attributes to add to each button .
* @ return
* A themed HTML string representing the radio button set .
*/
2004-06-04 18:10:05 +00:00
function form_radios ( $title , $name , $value , $options , $description = NULL , $required = FALSE , $attributes = NULL ) {
2003-12-24 12:40:28 +00:00
if ( count ( $options ) > 0 ) {
2004-04-12 08:27:57 +00:00
$choices = '' ;
2003-12-24 12:40:28 +00:00
foreach ( $options as $key => $choice ) {
2004-07-13 07:21:14 +00:00
$choices .= '<label class="option"><input type="radio" class="form-radio" name="edit[' . $name . ']" value="' . $key . '"' . ( $key == $value ? ' checked="checked"' : '' ) . drupal_attributes ( $attributes ) . ' /> ' . $choice . '</label><br />' ;
2003-12-24 12:40:28 +00:00
}
2004-07-08 11:31:12 +00:00
return theme ( 'form_element' , $title , $choices , $description , $name , $required , _form_get_error ( $name ));
2003-12-24 12:40:28 +00:00
}
2003-04-13 13:42:51 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Format a checkbox .
*
* @ param $title
* The label for the checkbox .
* @ param $name
* The internal name used to refer to the button .
* @ param $value
* The value that the form element takes on when selected .
* @ param $checked
* Whether the button will be initially selected when the page is rendered .
* @ param $description
* Explanatory text to display after the form item .
* @ param $attributes
* An associative array of HTML attributes to add to the button .
* @ param $required
* Whether the user must check this box before submitting the form .
* @ return
* A themed HTML string representing the checkbox .
*/
function form_checkbox ( $title , $name , $value = 1 , $checked = FALSE , $description = NULL , $attributes = NULL , $required = FALSE ) {
$element = '<input type="checkbox" class="' . _form_get_class ( 'form-checkbox' , $required , _form_get_error ( $name )) . '" name="edit[' . $name . ']" id="edit-' . $name . '" value="' . $value . '"' . ( $checked ? ' checked="checked"' : '' ) . drupal_attributes ( $attributes ) . ' />' ;
2004-02-24 20:22:45 +00:00
if ( ! is_null ( $title )) {
2004-07-13 07:21:14 +00:00
$element = '<label class="option">' . $element . ' ' . $title . '</label>' ;
2004-02-24 20:22:45 +00:00
}
2004-07-08 11:31:12 +00:00
return form_hidden ( $name , 0 ) . theme ( 'form_element' , NULL , $element , $description , $name , $required , _form_get_error ( $name ));
2001-12-01 15:20:48 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Format a set of checkboxes .
*
* @ param $title
* The label for the checkboxes as a group .
* @ param $name
* The internal name used to refer to the buttons .
* @ param $values
* A linear array of keys of the initally checked boxes .
* @ param $options
* An associative array of buttons to display . The keys in this array are
* button values , while the values are the labels to display for each button .
* @ param $description
* Explanatory text to display after the form item .
* @ param $attributes
* An associative array of HTML attributes to add to each button .
* @ param $required
* Whether the user must check a box before submitting the form .
* @ return
* A themed HTML string representing the radio button set .
*/
2004-07-08 11:31:12 +00:00
function form_checkboxes ( $title , $name , $values , $options , $description = NULL , $attributes = NULL , $required = FALSE ) {
2004-05-15 15:42:47 +00:00
if ( count ( $options ) > 0 ) {
if ( ! isset ( $values )) {
$values = array ();
}
$choices = '' ;
foreach ( $options as $key => $choice ) {
2004-07-13 07:21:14 +00:00
$choices .= '<label class="option"><input type="checkbox" class="form-checkbox" name="edit[' . $name . '][]" value="' . $key . '"' . ( in_array ( $key , $values ) ? ' checked="checked"' : '' ) . drupal_attributes ( $attributes ) . ' /> ' . $choice . '</label><br />' ;
2004-05-15 15:42:47 +00:00
}
2004-07-08 11:31:12 +00:00
return theme ( 'form_element' , $title , $choices , $description , $name , $required , _form_get_error ( $name ));
2004-05-15 15:42:47 +00:00
}
}
2004-07-13 07:21:14 +00:00
/**
* Format a single - line text field .
*
* @ param $title
* The label for the text field .
* @ param $name
* The internal name used to refer to the field .
* @ param $value
* The initial value for the field at page load time .
* @ param $size
* A measure of the visible size of the field ( passed directly to HTML ) .
* @ param $maxlength
* The maximum number of characters that may be entered in the field .
* @ param $description
* Explanatory text to display after the form item .
* @ param $attributes
* An associative array of HTML attributes to add to the form item .
* @ param $required
* Whether the user must enter some text in the field .
* @ return
* A themed HTML string representing the field .
*/
2004-04-24 15:39:31 +00:00
function form_textfield ( $title , $name , $value , $size , $maxlength , $description = NULL , $attributes = NULL , $required = FALSE ) {
2004-07-13 07:21:14 +00:00
$size = $size ? ' size="' . $size . '"' : '' ;
return theme ( 'form_element' , $title , '<input type="text" maxlength="' . $maxlength . '" class="' . _form_get_class ( 'form-text' , $required , _form_get_error ( $name )) . '" name="edit[' . $name . ']" id="' . $name . '"' . $size . ' value="' . check_form ( $value ) . '"' . drupal_attributes ( $attributes ) . ' />' , $description , $name , $required , _form_get_error ( $name ));
2001-12-01 15:20:48 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Format a single - line text field that does not display its contents visibly .
*
* @ param $title
* The label for the text field .
* @ param $name
* The internal name used to refer to the field .
* @ param $value
* The initial value for the field at page load time .
* @ param $size
* A measure of the visible size of the field ( passed directly to HTML ) .
* @ param $maxlength
* The maximum number of characters that may be entered in the field .
* @ param $description
* Explanatory text to display after the form item .
* @ param $attributes
* An associative array of HTML attributes to add to the form item .
* @ param $required
* Whether the user must enter some text in the field .
* @ return
* A themed HTML string representing the field .
*/
2004-04-24 15:39:31 +00:00
function form_password ( $title , $name , $value , $size , $maxlength , $description = NULL , $attributes = NULL , $required = FALSE ) {
2004-07-13 07:21:14 +00:00
$size = $size ? ' size="' . $size . '"' : '' ;
return theme ( 'form_element' , $title , '<input type="password" class="' . _form_get_class ( 'form-password' , $required , _form_get_error ( $name )) . '" maxlength="' . $maxlength . '" name="edit[' . $name . ']" id="' . $name . '"' . $size . ' value="' . check_form ( $value ) . '"' . drupal_attributes ( $attributes ) . ' />' , $description , $name , $required , _form_get_error ( $name ));
2001-12-01 15:20:48 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Format a multiple - line text field .
*
* @ param $title
* The label for the text field .
* @ param $name
* The internal name used to refer to the field .
* @ param $value
* The initial value for the field at page load time .
* @ param $cols
* The width of the field , in columns of text .
* @ param $rows
* The height of the field , in rows of text .
* @ param $description
* Explanatory text to display after the form item .
* @ param $attributes
* An associative array of HTML attributes to add to the form item .
* @ param $required
* Whether the user must enter some text in the field .
* @ return
* A themed HTML string representing the field .
*/
2004-04-24 15:39:31 +00:00
function form_textarea ( $title , $name , $value , $cols , $rows , $description = NULL , $attributes = NULL , $required = FALSE ) {
2004-07-13 07:21:14 +00:00
$cols = $cols ? ' cols="' . $cols . '"' : '' ;
module_invoke_all ( 'textarea' , $name ); // eg. optionally plug in a WYSIWYG editor
return theme ( 'form_element' , $title , '<textarea wrap="virtual"' . $cols . ' rows="' . $rows . '" name="edit[' . $name . ']" id="' . $name . '" class="' . _form_get_class ( 'textarea' , $required , _form_get_error ( $name )) . '"' . drupal_attributes ( $attributes ) . '>' . check_form ( $value ) . '</textarea>' , $description , $name , $required , _form_get_error ( $name ));
2001-12-01 15:20:48 +00:00
}
2004-05-05 15:58:26 +00:00
/**
2004-07-13 07:21:14 +00:00
* Format a dropdown menu or scrolling selection box .
2004-05-05 15:58:26 +00:00
*
2004-07-13 07:21:14 +00:00
* @ param $title
* The label for the form element .
* @ param $name
* The internal name used to refer to the form element .
* @ param $value
* The key of the currently selected item , or a linear array of keys of all the
* currently selected items if multiple selections are allowed .
* @ param $options
* An associative array of buttons to display . The keys in this array are
* button values , while the values are the labels to display for each button .
* @ param $description
* Explanatory text to display after the form item .
* @ param $extra
* Additional HTML to inject into the select element tag .
* @ param $multiple
* Whether the user may select more than one item .
* @ param $required
* Whether the user must select a value before submitting the form .
* @ return
* A themed HTML string representing the form element .
2004-05-05 15:58:26 +00:00
*
2004-07-13 07:21:14 +00:00
* It is possible to group options together ; to do this , change the format of
* $options to an associative array in which the keys are group labels , and the
* values are associative arrays in the normal $options format .
2004-05-05 15:58:26 +00:00
*/
2004-07-13 07:21:14 +00:00
function form_select ( $title , $name , $value , $options , $description = NULL , $extra = 0 , $multiple = FALSE , $required = FALSE ) {
2004-04-12 08:27:57 +00:00
$select = '' ;
2003-12-24 12:40:28 +00:00
foreach ( $options as $key => $choice ) {
2004-05-05 15:58:26 +00:00
if ( is_array ( $choice )) {
2004-07-13 07:21:14 +00:00
$select .= '<optgroup label="' . $key . '">' ;
2004-05-05 15:58:26 +00:00
foreach ( $choice as $key => $choice ) {
2004-07-13 07:21:14 +00:00
$select .= '<option value="' . $key . '"' . ( is_array ( $value ) ? ( in_array ( $key , $value ) ? ' selected="selected"' : '' ) : ( $value == $key ? ' selected="selected"' : '' )) . '>' . check_form ( $choice ) . '</option>' ;
2004-05-05 15:58:26 +00:00
}
2004-07-13 07:21:14 +00:00
$select .= '</optgroup>' ;
2004-05-05 15:58:26 +00:00
}
else {
2004-07-13 07:21:14 +00:00
$select .= '<option value="' . $key . '"' . ( is_array ( $value ) ? ( in_array ( $key , $value ) ? ' selected="selected"' : '' ) : ( $value == $key ? ' selected="selected"' : '' )) . '>' . check_form ( $choice ) . '</option>' ;
2004-05-05 15:58:26 +00:00
}
2003-06-05 18:09:39 +00:00
}
2004-07-13 07:21:14 +00:00
return theme ( 'form_element' , $title , '<select name="edit[' . $name . ']' . ( $multiple ? '[]' : '' ) . '"' . ( $multiple ? ' multiple="multiple" ' : '' ) . ( $extra ? ' ' . $extra : '' ) . ' id="' . $name . '">' . $select . '</select>' , $description , $name , $required , _form_get_error ( $name ));
2003-06-05 18:09:39 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Format a file upload field .
*
* @ param $title
* The label for the file upload field .
* @ param $name
* The internal name used to refer to the field .
* @ param $size
* A measure of the visible size of the field ( passed directly to HTML ) .
* @ param $description
* Explanatory text to display after the form item .
* @ param $required
* Whether the user must upload a file to the field .
* @ return
* A themed HTML string representing the field .
*
* For assistance with handling the uploaded file correctly , see the API
* provided by file . inc .
*/
2004-04-24 15:39:31 +00:00
function form_file ( $title , $name , $size , $description = NULL , $required = FALSE ) {
2004-07-13 07:21:14 +00:00
return theme ( 'form_element' , $title , '<input type="file" class="' . _form_get_class ( 'form-file' , $required , _form_get_error ( $name )) . '" name="edit[' . $name . ']" id="' . $name . '" size="' . $size . " \" /> \n " , $description , $name , $required , _form_get_error ( $error ));
2001-12-01 15:20:48 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Store data in a hidden form field .
*
* @ param $name
* The internal name used to refer to the field .
* @ param $value
* The stored data .
* @ return
* A themed HTML string representing the hidden field .
*
* This function can be useful in retaining information between page requests ,
* but be sure to validate the data on the receiving page as it is possible for
* an attacker to change the value before it is submitted .
*/
2001-12-01 15:20:48 +00:00
function form_hidden ( $name , $value ) {
2004-07-13 07:21:14 +00:00
return '<input type="hidden" name="edit[' . $name . ']" value="' . check_form ( $value ) . " \" /> \n " ;
2001-12-01 15:20:48 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Format an action button .
*
* @ param $value
* Both the label for the button , and the value passed to the target page
* when this button is clicked .
* @ param $name
* The internal name used to refer to the button .
* @ param $type
* What type to pass to the HTML input tag .
* @ param $attributes
* An associative array of HTML attributes to add to the form item .
* @ return
* A themed HTML string representing the button .
*/
function form_button ( $value , $name = 'op' , $type = 'submit' , $attributes = NULL ) {
return '<input type="' . $type . '" class="form-' . $type . '" name="' . $name . '" value="' . check_form ( $value ) . '" ' . drupal_attributes ( $attributes ) . " /> \n " ;
2003-12-15 19:58:53 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Format a form submit button .
*
* @ param $value
* Both the label for the button , and the value passed to the target page
* when this button is clicked .
* @ param $name
* The internal name used to refer to the button .
* @ param $attributes
* An associative array of HTML attributes to add to the form item .
* @ return
* A themed HTML string representing the button .
*/
function form_submit ( $value , $name = 'op' , $attributes = NULL ) {
return form_button ( $value , $name , 'submit' , $attributes );
2001-12-01 15:20:48 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Format a weight selection menu .
*
* @ param $title
* The label for the form element .
* @ param $name
* The internal name used to refer to the form element .
* @ param $value
* The selected weight value at page load time .
* @ param $delta
* The largest in absolute value the weight can be . For example , if set to 10 ,
* weights could range from - 10 to 10 inclusive .
* @ param $description
* Explanatory text to display after the form item .
* @ param $extra
* Additional HTML to inject into the select element tag .
* @ return
* A themed HTML string representing the form element .
*/
function form_weight ( $title = NULL , $name = 'weight' , $value = 0 , $delta = 10 , $description = NULL , $extra = 0 ) {
2003-04-03 22:18:27 +00:00
for ( $n = ( - 1 * $delta ); $n <= $delta ; $n ++ ) {
2002-10-26 15:17:26 +00:00
$weights [ $n ] = $n ;
}
return form_select ( $title , $name , $value , $weights , $description , $extra );
}
2004-01-06 19:52:14 +00:00
/* @} */
2003-06-19 17:26:27 +00:00
2004-07-13 07:21:14 +00:00
/**
* Generate an internal Drupal URL .
*
* @ param $path
* The Drupal path being linked to , such as " admin/node " .
* @ param $query
* A query string to append to the link .
* @ param $fragment
* A fragment identifier ( named anchor ) to append to the link .
* @ param $absolute
* Whether to force the output to be an absolute link ( beginning with http : ) .
* Useful for links that will be displayed outside the site , such as in an RSS feed .
* @ return
* an HTML string containing a link to the given path .
*
* When creating links in modules , consider whether l () could be a better
* alternative than url () .
*/
function url ( $path = NULL , $query = NULL , $fragment = NULL , $absolute = FALSE ) {
2004-01-14 22:41:15 +00:00
global $base_url ;
2004-01-17 23:19:02 +00:00
2003-05-31 13:05:06 +00:00
static $script ;
if ( empty ( $script )) {
/*
** On some webservers such as IIS we can ' t omit " index.php " . As such we
** generate " index.php?q=foo " instead of " ?q=foo " on anything that is not
** Apache .
*/
2004-07-13 07:21:14 +00:00
$script = ( strpos ( $_SERVER [ 'SERVER_SOFTWARE' ], 'Apache' ) === false ) ? 'index.php' : '' ;
2003-05-31 13:05:06 +00:00
}
2004-07-13 07:21:14 +00:00
$path = drupal_get_path_alias ( $path );
2003-09-30 17:01:34 +00:00
2003-12-29 19:10:26 +00:00
if ( isset ( $fragment )) {
2004-07-13 07:21:14 +00:00
$fragment = '#' . $fragment ;
2003-12-29 19:10:26 +00:00
}
2004-02-11 19:21:14 +00:00
$base = ( $absolute ? $base_url . '/' : '' );
2004-07-13 07:21:14 +00:00
if ( variable_get ( 'clean_url' , '0' ) == '0' ) {
if ( isset ( $path )) {
2003-02-14 19:52:45 +00:00
if ( isset ( $query )) {
2004-07-13 07:21:14 +00:00
return $base . $script . '?q=' . $path . '&' . $query . $fragment ;
2003-02-14 19:52:45 +00:00
}
else {
2004-07-13 07:21:14 +00:00
return $base . $script . '?q=' . $path . $fragment ;
2003-02-14 19:52:45 +00:00
}
2003-01-06 21:24:21 +00:00
}
else {
2003-02-14 19:52:45 +00:00
if ( isset ( $query )) {
2004-07-13 07:21:14 +00:00
return $base . $script . '?' . $query . $fragment ;
2003-02-14 19:52:45 +00:00
}
else {
2004-07-13 07:21:14 +00:00
return $base . $fragment ;
2003-02-14 19:52:45 +00:00
}
2003-01-06 21:24:21 +00:00
}
}
else {
2004-07-13 07:21:14 +00:00
if ( isset ( $path )) {
2003-02-14 19:52:45 +00:00
if ( isset ( $query )) {
2004-07-13 07:21:14 +00:00
return $base . $path . '?' . $query . $fragment ;
2003-02-14 19:52:45 +00:00
}
else {
2004-07-13 07:21:14 +00:00
return $base . $path . $fragment ;
2003-02-14 19:52:45 +00:00
}
2003-01-06 21:24:21 +00:00
}
2003-01-11 10:46:11 +00:00
else {
2003-02-14 19:52:45 +00:00
if ( isset ( $query )) {
2004-07-13 07:21:14 +00:00
return $base . $script . '?' . $query . $fragment ;
2003-02-14 19:52:45 +00:00
}
else {
2004-07-13 07:21:14 +00:00
return $base . $fragment ;
2003-02-14 19:52:45 +00:00
}
2003-01-11 10:46:11 +00:00
}
2003-01-06 21:24:21 +00:00
}
2002-04-20 11:52:50 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Format an attribute string to insert in a tag .
*
* @ param $attributes
* An associative array of HTML attributes .
* @ return
* An HTML string ready for insertion in a tag .
*/
2004-03-10 19:32:37 +00:00
function drupal_attributes ( $attributes = array ()) {
2004-07-08 11:31:12 +00:00
if ( $attributes ) {
2003-08-12 20:37:16 +00:00
$t = array ();
foreach ( $attributes as $key => $value ) {
2004-07-13 07:21:14 +00:00
$t [] = $key . '="' . $value . '"' ;
2003-08-12 20:37:16 +00:00
}
2004-03-10 19:32:37 +00:00
2004-07-13 07:21:14 +00:00
return ' ' . implode ( $t , ' ' );
2002-04-27 13:19:37 +00:00
}
2003-08-12 20:37:16 +00:00
}
2003-01-06 19:51:01 +00:00
2004-07-13 07:21:14 +00:00
/**
* Format an internal Drupal link .
*
* This function correctly handles aliased paths , and allows themes to highlight
* links to the current page correctly , so all internal links output by modules
* should be generated by this function if possible .
*
* @ param $text
* The text to be enclosed with the anchor tag .
* @ param $path
* The Drupal path being linked to , such as " admin/node " .
* @ param $attributes
* An associative array of HTML attributes to apply to the anchor tag .
* @ param $query
* A query string to append to the link .
* @ param $fragment
* A fragment identifier ( named anchor ) to append to the link .
* @ param $absolute
* Whether to force the output to be an absolute link ( beginning with http : ) .
* Useful for links that will be displayed outside the site , such as in an RSS feed .
* @ return
* an HTML string containing a link to the given path .
*/
function l ( $text , $path , $attributes = array (), $query = NULL , $fragment = NULL , $absolute = FALSE ) {
if ( drupal_get_normal_path ( $path ) == $_GET [ 'q' ]) {
2004-01-19 21:57:42 +00:00
if ( isset ( $attributes [ 'class' ])) {
$attributes [ 'class' ] .= ' active' ;
}
else {
$attributes [ 'class' ] = 'active' ;
}
}
2004-07-13 07:21:14 +00:00
return '<a href="' . url ( $path , $query , $fragment , $absolute ) . '"' . drupal_attributes ( $attributes ) . '>' . $text . '</a>' ;
2002-04-20 11:52:50 +00:00
}
2001-12-01 15:20:48 +00:00
function field_get ( $string , $name ) {
2004-01-23 15:31:29 +00:00
ereg ( " , $name =([^,]+) " , " , $string " , $regs );
2001-12-01 15:20:48 +00:00
return $regs [ 1 ];
}
function field_set ( $string , $name , $value ) {
$rval = ereg_replace ( " , $name =[^,]+ " , " " , " , $string " );
2003-01-09 20:06:00 +00:00
if ( isset ( $value )) {
2004-07-13 07:21:14 +00:00
$rval .= ( $rval == ',' ? '' : ',' ) . $name . '=' . $value ;
2002-03-05 20:15:17 +00:00
}
2001-12-01 15:20:48 +00:00
return substr ( $rval , 1 );
}
2004-07-13 07:21:14 +00:00
/**
* Fetch a set of global navigation links .
*
* The links are gathered by calls to hook_link ( 'page' ) in each module .
*/
2001-12-01 15:20:48 +00:00
function link_page () {
2003-08-11 20:41:37 +00:00
global $custom_links ;
2002-04-14 20:46:41 +00:00
2003-09-05 13:19:00 +00:00
if ( is_array ( $custom_links )) {
2002-04-02 09:45:57 +00:00
return $custom_links ;
}
else {
2004-07-13 07:21:14 +00:00
$links = module_invoke_all ( 'link' , 'page' );
array_unshift ( $links , l ( t ( 'home' ), '' , array ( 'title' => t ( 'Return to the main page.' ))));
2002-04-02 09:45:57 +00:00
return $links ;
2001-12-01 15:20:48 +00:00
}
2002-04-14 20:46:41 +00:00
}
2001-12-01 15:20:48 +00:00
2004-07-13 07:21:14 +00:00
/**
* Fetch a set of links to display after a given node .
*
* The links are gathered by calls to hook_link ( 'node' ) in each module .
*/
2001-12-01 15:20:48 +00:00
function link_node ( $node , $main = 0 ) {
2004-07-13 07:21:14 +00:00
return module_invoke_all ( 'link' , 'node' , $node , $main );
2001-12-01 15:20:48 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Perform end - of - request tasks .
*
* This function sets the page cache if appropriate , and allows modules to
* react to the closing of the page by calling hook_exit () .
*/
2003-05-18 09:48:49 +00:00
function drupal_page_footer () {
2004-07-13 07:21:14 +00:00
if ( variable_get ( 'cache' , 0 )) {
2002-01-05 16:28:34 +00:00
page_set_cache ();
2001-12-01 15:20:48 +00:00
}
2003-01-26 13:22:02 +00:00
2004-07-13 07:21:14 +00:00
module_invoke_all ( 'exit' );
2001-12-01 15:20:48 +00:00
}
2004-02-12 19:37:04 +00:00
/**
2004-07-13 07:21:14 +00:00
* Form an associative array from a linear array .
2004-02-12 19:37:04 +00:00
*
2004-07-13 07:21:14 +00:00
* This function walks through the provided array and constructs an associative
* array out of it . The keys of the resulting array will be the values of the
* input array . The values will be the same as the keys unless a function is
* specified , in which case the output of the function is used for the values
* instead .
*
* @ param $array
* A linear array .
* @ param $function
* The name of a function to apply to all values before output .
* @ result
* An associative array .
2004-02-12 19:37:04 +00:00
*/
function drupal_map_assoc ( $array , $function = NULL ) {
if ( ! isset ( $function )) {
$result = array ();
foreach ( $array as $value ) {
$result [ $value ] = $value ;
}
return $result ;
}
elseif ( function_exists ( $function )) {
$result = array ();
foreach ( $array as $value ) {
$result [ $value ] = $function ( $value );
}
return $result ;
}
}
2004-01-06 12:09:42 +00:00
/**
2004-07-13 07:21:14 +00:00
* Prepare a new XML parser .
*
* This is a wrapper around xml_parser_create () which extracts the encoding from
* the XML data first and sets the output encoding to UTF - 8. This function should
* be used instead of xml_parser_create (), because PHP 's XML parser doesn' t check
2004-01-06 12:09:42 +00:00
* the input encoding itself .
*
* This is also where unsupported encodings should be converted .
* Callers should take this into account : $data might have been changed after
* the call .
*
2004-07-13 07:21:14 +00:00
* @ param & $data
* The XML data which will be parsed later .
* @ return
* An XML parser object .
2004-01-06 12:09:42 +00:00
*/
function drupal_xml_parser_create ( & $data ) {
$encoding = 'utf-8' ;
if ( ereg ( '^<\?xml[^>]+encoding="([^"]+)"' , $data , $match )) {
$encoding = $match [ 1 ];
}
/*
2004-02-17 23:36:22 +00:00
* Unsupported encodings are converted here into UTF - 8.
2004-07-12 21:35:31 +00:00
* Requires the iconv , GNU recode or mbstring PHP extension .
2004-01-06 12:09:42 +00:00
*/
2004-02-17 23:36:22 +00:00
$php_supported = array ( 'utf-8' , 'iso-8859-1' , 'us-ascii' );
if ( ! in_array ( strtolower ( $encoding ), $php_supported )) {
if ( function_exists ( 'iconv' )) {
2004-07-12 21:35:31 +00:00
$out = @ iconv ( $encoding , 'utf-8' , $data );
2004-02-17 23:36:22 +00:00
}
2004-07-12 21:35:31 +00:00
else if ( function_exists ( 'mb_convert_encoding' )) {
$out = @ mb_convert_encoding ( $data , 'utf-8' , $encoding );
}
else if ( function_exists ( 'recode_string' )) {
$out = @ recode_string ( $encoding . '..utf-8' , $data );
}
else {
2004-07-13 07:21:14 +00:00
watchdog ( t ( " Unsupported XML encoding '%s'. Please install iconv, GNU recode or mbstring for PHP. " , $encoding ));
2004-07-12 21:35:31 +00:00
return 0 ;
}
2004-07-12 21:38:41 +00:00
if ( $out !== false ) {
$data = $out ;
$encoding = 'utf-8' ;
}
else {
2004-07-13 07:21:14 +00:00
watchdog ( t ( " Could not convert XML encoding '%s' to UTF-8. " , $encoding ));
2004-07-12 21:38:41 +00:00
return 0 ;
}
2004-02-17 23:36:22 +00:00
}
2004-01-06 12:09:42 +00:00
$xml_parser = xml_parser_create ( $encoding );
xml_parser_set_option ( $xml_parser , XML_OPTION_TARGET_ENCODING , 'utf-8' );
return $xml_parser ;
}
2004-04-15 14:07:08 +00:00
/**
2004-07-13 07:21:14 +00:00
* Truncate a UTF - 8 - encoded string safely .
*
2004-04-15 14:07:08 +00:00
* If the end position is in the middle of a UTF - 8 sequence , it scans backwards
* until the beginning of the byte sequence .
*
* Use this function whenever you want to chop off a string at an unsure
* location . On the other hand , if you 're sure that you' re splitting on a
* character boundary ( e . g . after using strpos or similar ), you can safely use
* substr () instead .
*
2004-07-13 07:21:14 +00:00
* @ param $string
* The string to truncate .
* @ param $len
* An upper limit on the returned string length .
* @ return
* The truncated string .
2004-04-15 14:07:08 +00:00
*/
function truncate_utf8 ( $string , $len ) {
$slen = strlen ( $string );
if ( $slen <= $len ) {
return $string ;
}
if (( ord ( $string [ $len ]) < 0x80 ) || ( ord ( $string [ $len ]) >= 0xC0 )) {
return substr ( $string , 0 , $len );
}
while ( ord ( $string [ -- $len ]) < 0xC0 ) {};
return substr ( $string , 0 , $len );
}
2004-07-13 07:21:14 +00:00
include_once 'includes/theme.inc' ;
include_once 'includes/pager.inc' ;
include_once 'includes/menu.inc' ;
include_once 'includes/xmlrpc.inc' ;
include_once 'includes/tablesort.inc' ;
include_once 'includes/file.inc' ;
2003-02-12 16:21:48 +00:00
2003-03-04 06:19:01 +00:00
// set error handler:
2004-07-13 07:21:14 +00:00
set_error_handler ( 'error_handler' );
2003-03-04 06:19:01 +00:00
2003-06-04 18:24:39 +00:00
// spit out the correct charset http header
2004-07-13 07:21:14 +00:00
drupal_set_header ( 'Content-Type: text/html; charset=utf-8' );
2003-06-04 18:24:39 +00:00
2004-07-13 07:21:14 +00:00
// initialize the _GET['q'] prior to loading the modules and invoking their 'init' hook:
if ( ! empty ( $_GET [ 'q' ])) {
$_GET [ 'q' ] = drupal_get_normal_path ( trim ( $_GET [ 'q' ], '/' ));
2003-09-30 17:01:34 +00:00
}
else {
2004-07-13 07:21:14 +00:00
$_GET [ 'q' ] = drupal_get_normal_path ( variable_get ( 'site_frontpage' , 'node' ));
2003-09-30 17:01:34 +00:00
}
2003-03-17 07:01:12 +00:00
// initialize installed modules:
module_init ();
2004-07-13 07:21:14 +00:00
if ( $_REQUEST && ! user_access ( 'bypass input data check' )) {
2003-11-18 19:44:36 +00:00
if ( ! valid_input_data ( $_REQUEST )) {
2004-07-13 07:21:14 +00:00
die ( 'terminated request because of suspicious input data' );
2003-11-18 19:44:36 +00:00
}
}
2001-12-01 15:20:48 +00:00
// initialize localization system:
$locale = locale_init ();
// initialize theme:
2003-11-09 23:27:22 +00:00
$theme = init_theme ();
2003-11-18 19:44:36 +00:00
2003-03-04 15:10:37 +00:00
?>