mobile_tools.module in Mobile Tools 6
Same filename and directory in other branches
Mobile Tools provides a range of functionality assisting in creating a mobile Drupal site . this functionality contains:
- User Agent detection ('mobile' or 'desktop')
- automatic redirection towards mobile site or user notification by means of a block message or drupal_set_message
- Adding a mobile context to the permission system
- Adding a mobile context to theming (= theme switching or separate configuration for desktop and )
For more documentation and examples please go to http://drupal.org/node/459686
File
mobile_tools.moduleView source
<?php
/**
* @file
* Mobile Tools provides a range of functionality assisting in creating a mobile Drupal site . this functionality contains:
* - User Agent detection ('mobile' or 'desktop')
* - automatic redirection towards mobile site or user notification by means of a block message or drupal_set_message
* - Adding a mobile context to the permission system
* - Adding a mobile context to theming (= theme switching or separate configuration for desktop and )
*
* For more documentation and examples please go to http://drupal.org/node/459686
*/
/* The default messages being displayed to the users . these can be overwritten in
* the configuration panel
*/
define('MOBILE_NOTIFICATION', '<a href="">Mobile View</a>');
define('DESKTOP_NOTIFICATION', '<a href="">Regular View</a>');
/**
* Implementation of hook_help($section).
*/
function mobile_tools_help($path, $arg) {
switch ($path) {
case 'admin/help#mobile_tools':
return '<p>' . t('Visit the !documentation for more info', array(
'!documentation' => l('documentation page', 'http://drupal.org/node/459686'),
)) . '<p>';
}
}
/**
* Implementation of hook_perm().
*/
function mobile_tools_perm() {
return array(
'configure Mobile Tools',
);
}
/**
* Implementation of hook_menu().
*/
function mobile_tools_menu() {
$items['admin/settings/mobile-tools'] = array(
'title' => 'Mobile Tools',
'description' => t('Configure the detection of the mobile client and the appropriate actions.'),
'access arguments' => array(
'configure Mobile Tools',
),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'mobile_tools_configuration_form',
),
'type' => MENU_NORMAL_ITEM,
'file' => 'mobile_tools.admin.inc',
);
$items['admin/settings/mobile-tools/device-detection'] = array(
'title' => 'Notification / redirection',
'description' => 'Configure the detection of the mobile client and the appropriate actions (notifications or redirection)',
'access arguments' => array(
'configure Mobile Tools',
),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -4,
'file' => 'mobile_tools.admin.inc',
);
$items['admin/settings/mobile-tools/themes'] = array(
'title' => 'Theme Switching',
'page arguments' => array(
'mobile_tools_themes_configuration_form',
),
'page callback' => 'drupal_get_form',
'access arguments' => array(
'configure Mobile Tools',
),
'type' => MENU_LOCAL_TASK,
'weight' => 0,
'file' => 'mobile_tools.admin.inc',
);
$items['admin/settings/mobile-tools/roles'] = array(
'title' => 'Mobile roles',
'page arguments' => array(
'mobile_tools_roles_configuration_form',
),
'page callback' => 'drupal_get_form',
'access arguments' => array(
'configure Mobile Tools',
),
'type' => MENU_LOCAL_TASK,
'file' => 'mobile_tools_roles.inc',
'weight' => 0,
'file' => 'mobile_tools_roles.inc',
);
$items['admin/settings/mobile-tools/ext'] = array(
'title' => 'External modules',
'page arguments' => array(
'mobile_tools_external_modules_configuration_form',
),
'page callback' => 'drupal_get_form',
'access arguments' => array(
'configure Mobile Tools',
),
'type' => MENU_LOCAL_TASK,
'weight' => 10,
'file' => 'mobile_tools.admin.inc',
);
return $items;
}
/**
* Implementation of hook_block()
* Provides the blocks that can be used to show a message to the user to go to the
* mobile or desktop version.
*/
function mobile_tools_block($op = 'list', $delta = 0, $edit = array()) {
switch ($op) {
case 'list':
$blocks[0]['info'] = t('Mobile Tools message block');
$blocks[0]['cache'] = BLOCK_NO_CACHE;
return $blocks;
break;
case 'view':
$block['content'] = mobile_tools_block_message();
return $block;
break;
}
}
/**
* Helper function returning the configurable message for the notification
*/
function mobile_tools_block_message() {
$device = mobile_tools_get_device();
$site = mobile_tools_is_mobile_site();
if (variable_get('mobile_tools_mobile_url', '') != variable_get('mobile_tools_desktop_url', '')) {
if ($site == 'mobile') {
return variable_get('mobile_notification', MOBILE_NOTIFICATION);
}
else {
return variable_get('desktop_notification', DESKTOP_NOTIFICATION);
}
}
else {
if ($device['type'] == 'mobile') {
return variable_get('mobile_notification', MOBILE_NOTIFICATION);
}
else {
return variable_get('desktop_notification', DESKTOP_NOTIFICATION);
}
}
}
/**
* Implementation of hook_boot().
* Hook boot is called for both anonymous users and logged in users
*/
function mobile_tools_boot() {
global $conf, $user, $base_url;
// Get the device object
$device = mobile_tools_get_device();
// First call the redirect function. This will redirect the userif needed.
if (variable_get('mobile_tools_redirect', FALSE)) {
$redirected = mobile_tools_device_redirect($device);
}
// Switch theme if needed
$theme_switched = mobile_tools_switch_theme($device);
// Some small extras
if (mobile_tools_is_mobile_site() == 'mobile' || $theme_switched) {
$conf['default_nodes_main'] = variable_get('default_nodes_main_mobile', variable_get('default_nodes_main', 10));
$conf['site_frontpage'] = variable_get('site_frontpage_mobile', variable_get('site_frontpage', 'node'));
}
// include the mobile tools roles file if the setting is enabled
if (variable_get('mobile_tools_enable_roles', 0)) {
include dirname(__FILE__) . '/mobile_tools_roles.inc';
mobile_tools_roles_boot();
// assigns the user the mobile role
}
}
/**
* Being called in the hook_boot() implementation
* This function is in charge of redirection or displaying a notification
* @param $device
* The device object array('type' => [mobile/desktop], 'group' => [group])
*/
function mobile_tools_device_redirect($device) {
global $base_url;
//only consider redirection if the mobile url and the destkop url are different
$mobile_url = variable_get('mobile_tools_mobile_url', '');
$desktop_url = variable_get('mobile_tools_desktop_url', '');
if ($mobile_url == $desktop_url) {
return;
}
// see if the user is currently requestin the mobile or desktop url
$current_url_type = mobile_tools_is_mobile_site();
// code takes into account path exceptions in the configuration.
$pages = variable_get('mobile_tools_redirect_exceptions', '');
$page_match = FALSE;
if (isset($_GET['q']) && $pages != '') {
//check if there is no exception in the redirect path (code comes from block.module)
include_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
$path = drupal_get_path_alias($_GET['q']);
// Compare with the internal and path alias (if any).
$page_match = drupal_match_path($path, $pages);
if ($path != $_GET['q']) {
$page_match = $page_match || drupal_match_path($_GET['q'], $pages);
}
}
// check if exceptions are pages on which to redirect, or not to redirect
if (variable_get('mobile_tools_redirect_exceptions', 0) == 'only-redirect') {
$page_match = !$page_match;
}
// Redirections
if (!$page_match) {
// The case where a mobile user is accessing the desktop site
if ($device['type'] == 'mobile' && $current_url_type == 'desktop') {
$destination_url = mobile_tools_get_redirect_url();
mobile_tools_goto($destination_url);
// The case where a desktop user is accessing the mobile site
}
elseif ($device['type'] == 'desktop' && $current_url_type == 'mobile') {
$destination = variable_get('mobile_tools_desktop_url', $base_url);
mobile_tools_goto($destination);
}
}
}
/**
* Being called in the hook_boot() implementation
* This function is in charge of changing to the mobile theme
*/
function mobile_tools_switch_theme($device) {
global $custom_theme, $conf;
// check if theme switching is forced
$current_url_type = mobile_tools_is_mobile_site();
if ($current_url_type == 'mobile' && variable_get('mobile-tools-theme-switch', '') == 'mobile-tools-mobile-url' || variable_get('mobile-tools-theme-switch', '') == 'mobile-tools-mobile-device' && $device['type'] == 'mobile') {
$group = $device['group'];
$mobile_detection_module = variable_get('mobile-tools-device-detection', 'mobile_tools');
if (variable_get($mobile_detection_module . '_' . $group . '_enable', '') == 1) {
$custom_theme = variable_get($mobile_detection_module . '_' . $group . '_theme', $conf['theme_default']);
return TRUE;
}
else {
$custom_theme = variable_get('mobile_tools_theme_name', $conf['theme_default']);
return TRUE;
}
}
return FALSE;
}
/**
* Get $device object.
* Check if the 'device' argument is present or a cookie is set to overwrite the device:
* - device=mobile => mobile view
* - device=desktop => desktop view
* - device=[group] => specific group view
* - device=auto => reset overwrite
* @return $device
* The $device object
*/
function mobile_tools_get_device() {
global $cookie_domain;
// Checking the possible arguments
$session_time = time() + variable_get('mobile_tools_cookie_session', 3600 * 24 * 30);
//first check if the device type is forced in the device argument
if (isset($_GET['device'])) {
switch ($_GET['device']) {
case 'desktop':
case 'mobile':
setCookie('mt_device', $_GET['device'], variable_get('mobile_tools_cookie_lifetime', $session_time), '/');
return array(
'type' => $_GET['device'],
'group' => '',
);
break;
case 'auto':
setCookie('mt_device', '', time() - 3600);
break;
default:
$device_groups = mobile_tools_device_groups();
if (isset($device_groups[$_GET['device']])) {
setCookie('mt_device', $_GET['device'], variable_get('mobile_tools_cookie_lifetime', $session_time), '/');
return array(
'type' => 'mobile',
'group' => $_GET['device'],
);
}
}
}
elseif (isset($_COOKIE['mt_device'])) {
switch ($_COOKIE['mt_device']) {
case 'desktop':
case 'mobile':
return array(
'type' => $_COOKIE['mt_device'],
'group' => '',
);
break;
case 'auto':
setCookie('mt_device', '', time() - 3600);
break;
default:
$device_groups = mobile_tools_device_groups();
if (isset($device_groups[$_COOKIE['mt_device']])) {
setCookie('mt_device', $_COOKIE['mt_device'], variable_get('mobile_tools_cookie_lifetime', $session_time), '/');
return array(
'type' => 'mobile',
'group' => $_COOKIE['mt_device'],
);
}
}
}
// backwards compatibility with the nomobile parameter
if (isset($_GET['nomobile'])) {
if (strtolower($_GET['nomobile']) == 'true') {
setCookie('mobile_tools_switch', 0, variable_get('mobile_tools_cookie_lifetime', $session_time), '/');
return array(
'type' => 'desktop',
'group' => '',
);
}
elseif (strtolower($_GET['nomobile']) == 'false') {
setCookie('mobile_tools_switch', 1, variable_get('mobile_tools_cookie_lifetime', $session_time), '/');
return array(
'type' => 'mobile',
'group' => '',
);
}
}
if (isset($_COOKIE['mobile_tools_switch'])) {
switch ($_COOKIE['mobile_tools_switch']) {
case '0':
return array(
'type' => 'desktop',
'group' => '',
);
case '1':
return array(
'type' => 'mobile',
'group' => '',
);
}
}
// we default to the real detection
return mobile_tools_is_mobile_device();
}
/**
* Detect the device
* @return $device
* The $device object. Other modules can implement the hook_is_mobile_device()
*/
function mobile_tools_is_mobile_device() {
$device_detection = variable_get('mobile-tools-device-detection', 'mobile_tools');
drupal_load('module', $device_detection);
if ($device_detection != 'mobile_tools') {
return module_invoke($device_detection, 'is_mobile_device');
}
else {
return _mobile_tools_is_mobile_device();
}
}
/**
* Default implementation of hook_is_mobile_device()
* @return $device
* The $device object
*/
function _mobile_tools_is_mobile_device() {
$mobile_browser = array(
'type' => 'desktop',
'group' => '',
);
// set mobile browser as FALSE till we can prove otherwise
if (array_key_exists('HTTP_USER_AGENT', $_SERVER)) {
$user_agent = $_SERVER['HTTP_USER_AGENT'];
}
else {
return FALSE;
}
// get the content accept value
// FIXME: this should be cleaned to ensure no nefarious input gets executed
if (array_key_exists('HTTP_ACCEPT', $_SERVER)) {
$accept = $_SERVER['HTTP_ACCEPT'];
}
else {
$accept = '';
}
switch (TRUE) {
case FALSE !== stripos($user_agent, 'ipad'):
$mobile_browser = array(
'type' => 'desktop',
'group' => 'ipad',
);
break;
case FALSE !== stripos($user_agent, 'ipod'):
// we find the words iphone or ipod in the user agent
$mobile_browser = array(
'type' => 'mobile',
'group' => 'ipod',
);
// mobile browser is either TRUE or FALSE depending on the setting of iphone when calling the function
break;
// break out and skip the rest if we've had a match on the iphone or ipod
case FALSE !== stripos($user_agent, 'iphone'):
// we find the words iphone or ipod in the user agent
$mobile_browser = array(
'type' => 'mobile',
'group' => 'iphone',
);
break;
case FALSE !== stripos($user_agent, 'android'):
// we find android in the user agent
$mobile_browser = array(
'type' => 'mobile',
'group' => 'android',
);
// mobile browser is either TRUE or FALSE depending on the setting of android when calling the function
break;
// break out and skip the rest if we've had a match on android
case FALSE !== stripos($user_agent, 'opera mini'):
// we find opera mini in the user agent
$mobile_browser = array(
'type' => 'mobile',
'group' => 'opera_mini',
);
// mobile browser is either TRUE or FALSE depending on the setting of opera when calling the function
break;
// break out and skip the rest if we've had a match on opera
case FALSE !== stripos($user_agent, 'blackberry'):
// we find blackberry in the user agent
$mobile_browser = array(
'type' => 'mobile',
'group' => 'blackberry',
);
// mobile browser is either TRUE or FALSE depending on the setting of blackberry when calling the function
break;
// break out and skip the rest if we've had a match on blackberry
case preg_match('/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|vodafone|o2|pocket|kindle|mobile|pda|psp|treo)/i', $user_agent):
// check if any of the values listed create a match on the user agent - these are some of the most common terms used in agents to identify them as being mobile devices - the i at the end makes it case insensitive
$mobile_browser = array(
'type' => 'mobile',
'group' => '',
);
// set mobile browser to TRUE
break;
// break out and skip the rest if we've preg_match on the user agent returned TRUE
case strpos($accept, 'text/vnd.wap.wml') > 0 || strpos($accept, 'application/vnd.wap.xhtml+xml') > 0:
// is the device showing signs of support for text/vnd.wap.wml or application/vnd.wap.xhtml+xml
$mobile_browser = array(
'type' => 'mobile',
'group' => '',
);
// set mobile browser to TRUE
break;
// break out and skip the rest if we've had a match on the content accept headers
case isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE']):
// is the device giving us a HTTP_X_WAP_PROFILE or HTTP_PROFILE header - only mobile devices would do this
$mobile_browser = array(
'type' => 'mobile',
'group' => '',
);
// set mobile browser to TRUE
break;
// break out and skip the final step if we've had a return TRUE on the mobile specfic headers
case in_array(strtolower(substr($user_agent, 0, 4)), array(
'1207' => '1207',
'3gso' => '3gso',
'4thp' => '4thp',
'501i' => '501i',
'502i' => '502i',
'503i' => '503i',
'504i' => '504i',
'505i' => '505i',
'506i' => '506i',
'6310' => '6310',
'6590' => '6590',
'770s' => '770s',
'802s' => '802s',
'a wa' => 'a wa',
'acer' => 'acer',
'acs-' => 'acs-',
'airn' => 'airn',
'alav' => 'alav',
'asus' => 'asus',
'attw' => 'attw',
'au-m' => 'au-m',
'aur ' => 'aur ',
'aus ' => 'aus ',
'abac' => 'abac',
'acoo' => 'acoo',
'aiko' => 'aiko',
'alco' => 'alco',
'alca' => 'alca',
'amoi' => 'amoi',
'anex' => 'anex',
'anny' => 'anny',
'anyw' => 'anyw',
'aptu' => 'aptu',
'arch' => 'arch',
'argo' => 'argo',
'bell' => 'bell',
'bird' => 'bird',
'bw-n' => 'bw-n',
'bw-u' => 'bw-u',
'beck' => 'beck',
'benq' => 'benq',
'bilb' => 'bilb',
'blac' => 'blac',
'c55/' => 'c55/',
'cdm-' => 'cdm-',
'chtm' => 'chtm',
'capi' => 'capi',
'comp' => 'comp',
'cond' => 'cond',
'craw' => 'craw',
'dall' => 'dall',
'dbte' => 'dbte',
'dc-s' => 'dc-s',
'dica' => 'dica',
'ds-d' => 'ds-d',
'ds12' => 'ds12',
'dait' => 'dait',
'devi' => 'devi',
'dmob' => 'dmob',
'doco' => 'doco',
'dopo' => 'dopo',
'el49' => 'el49',
'erk0' => 'erk0',
'esl8' => 'esl8',
'ez40' => 'ez40',
'ez60' => 'ez60',
'ez70' => 'ez70',
'ezos' => 'ezos',
'ezze' => 'ezze',
'elai' => 'elai',
'emul' => 'emul',
'eric' => 'eric',
'ezwa' => 'ezwa',
'fake' => 'fake',
'fly-' => 'fly-',
'fly_' => 'fly_',
'g-mo' => 'g-mo',
'g1 u' => 'g1 u',
'g560' => 'g560',
'gf-5' => 'gf-5',
'grun' => 'grun',
'gene' => 'gene',
'go.w' => 'go.w',
'good' => 'good',
'grad' => 'grad',
'hcit' => 'hcit',
'hd-m' => 'hd-m',
'hd-p' => 'hd-p',
'hd-t' => 'hd-t',
'hei-' => 'hei-',
'hp i' => 'hp i',
'hpip' => 'hpip',
'hs-c' => 'hs-c',
'htc ' => 'htc ',
'htc-' => 'htc-',
'htca' => 'htca',
'htcg' => 'htcg',
'htcp' => 'htcp',
'htcs' => 'htcs',
'htct' => 'htct',
'htc_' => 'htc_',
'haie' => 'haie',
'hita' => 'hita',
'huaw' => 'huaw',
'hutc' => 'hutc',
'i-20' => 'i-20',
'i-go' => 'i-go',
'i-ma' => 'i-ma',
'i230' => 'i230',
'iac' => 'iac',
'iac-' => 'iac-',
'iac/' => 'iac/',
'ig01' => 'ig01',
'im1k' => 'im1k',
'inno' => 'inno',
'iris' => 'iris',
'jata' => 'jata',
'java' => 'java',
'kddi' => 'kddi',
'kgt' => 'kgt',
'kgt/' => 'kgt/',
'kpt ' => 'kpt ',
'kwc-' => 'kwc-',
'klon' => 'klon',
'lexi' => 'lexi',
'lg g' => 'lg g',
'lg-a' => 'lg-a',
'lg-b' => 'lg-b',
'lg-c' => 'lg-c',
'lg-d' => 'lg-d',
'lg-f' => 'lg-f',
'lg-g' => 'lg-g',
'lg-k' => 'lg-k',
'lg-l' => 'lg-l',
'lg-m' => 'lg-m',
'lg-o' => 'lg-o',
'lg-p' => 'lg-p',
'lg-s' => 'lg-s',
'lg-t' => 'lg-t',
'lg-u' => 'lg-u',
'lg-w' => 'lg-w',
'lg/k' => 'lg/k',
'lg/l' => 'lg/l',
'lg/u' => 'lg/u',
'lg50' => 'lg50',
'lg54' => 'lg54',
'lge-' => 'lge-',
'lge/' => 'lge/',
'lynx' => 'lynx',
'leno' => 'leno',
'm1-w' => 'm1-w',
'm3ga' => 'm3ga',
'm50/' => 'm50/',
'maui' => 'maui',
'mc01' => 'mc01',
'mc21' => 'mc21',
'mcca' => 'mcca',
'medi' => 'medi',
'meri' => 'meri',
'mio8' => 'mio8',
'mioa' => 'mioa',
'mo01' => 'mo01',
'mo02' => 'mo02',
'mode' => 'mode',
'modo' => 'modo',
'mot ' => 'mot ',
'mot-' => 'mot-',
'mt50' => 'mt50',
'mtp1' => 'mtp1',
'mtv ' => 'mtv ',
'mate' => 'mate',
'maxo' => 'maxo',
'merc' => 'merc',
'mits' => 'mits',
'mobi' => 'mobi',
'motv' => 'motv',
'mozz' => 'mozz',
'n100' => 'n100',
'n101' => 'n101',
'n102' => 'n102',
'n202' => 'n202',
'n203' => 'n203',
'n300' => 'n300',
'n302' => 'n302',
'n500' => 'n500',
'n502' => 'n502',
'n505' => 'n505',
'n700' => 'n700',
'n701' => 'n701',
'n710' => 'n710',
'nec-' => 'nec-',
'nem-' => 'nem-',
'newg' => 'newg',
'neon' => 'neon',
'netf' => 'netf',
'noki' => 'noki',
'nzph' => 'nzph',
'o2 x' => 'o2 x',
'o2-x' => 'o2-x',
'opwv' => 'opwv',
'owg1' => 'owg1',
'opti' => 'opti',
'oran' => 'oran',
'p800' => 'p800',
'pand' => 'pand',
'pg-1' => 'pg-1',
'pg-2' => 'pg-2',
'pg-3' => 'pg-3',
'pg-6' => 'pg-6',
'pg-8' => 'pg-8',
'pg-c' => 'pg-c',
'pg13' => 'pg13',
'phil' => 'phil',
'pn-2' => 'pn-2',
'ppc;' => 'ppc;',
'pt-g' => 'pt-g',
'palm' => 'palm',
'pana' => 'pana',
'pire' => 'pire',
'pock' => 'pock',
'pose' => 'pose',
'psio' => 'psio',
'qa-a' => 'qa-a',
'qc-2' => 'qc-2',
'qc-3' => 'qc-3',
'qc-5' => 'qc-5',
'qc-7' => 'qc-7',
'qc07' => 'qc07',
'qc12' => 'qc12',
'qc21' => 'qc21',
'qc32' => 'qc32',
'qc60' => 'qc60',
'qci-' => 'qci-',
'qwap' => 'qwap',
'qtek' => 'qtek',
'r380' => 'r380',
'r600' => 'r600',
'raks' => 'raks',
'rim9' => 'rim9',
'rove' => 'rove',
's55/' => 's55/',
'sage' => 'sage',
'sams' => 'sams',
'sc01' => 'sc01',
'sch-' => 'sch-',
'scp-' => 'scp-',
'sdk/' => 'sdk/',
'se47' => 'se47',
'sec-' => 'sec-',
'sec0' => 'sec0',
'sec1' => 'sec1',
'semc' => 'semc',
'sgh-' => 'sgh-',
'shar' => 'shar',
'sie-' => 'sie-',
'sk-0' => 'sk-0',
'sl45' => 'sl45',
'slid' => 'slid',
'smb3' => 'smb3',
'smt5' => 'smt5',
'sp01' => 'sp01',
'sph-' => 'sph-',
'spv ' => 'spv ',
'spv-' => 'spv-',
'sy01' => 'sy01',
'samm' => 'samm',
'sany' => 'sany',
'sava' => 'sava',
'scoo' => 'scoo',
'send' => 'send',
'siem' => 'siem',
'smar' => 'smar',
'smit' => 'smit',
'soft' => 'soft',
'sony' => 'sony',
't-mo' => 't-mo',
't218' => 't218',
't250' => 't250',
't600' => 't600',
't610' => 't610',
't618' => 't618',
'tcl-' => 'tcl-',
'tdg-' => 'tdg-',
'telm' => 'telm',
'tim-' => 'tim-',
'ts70' => 'ts70',
'tsm-' => 'tsm-',
'tsm3' => 'tsm3',
'tsm5' => 'tsm5',
'tx-9' => 'tx-9',
'tagt' => 'tagt',
'talk' => 'talk',
'teli' => 'teli',
'topl' => 'topl',
'tosh' => 'tosh',
'up.b' => 'up.b',
'upg1' => 'upg1',
'utst' => 'utst',
'v400' => 'v400',
'v750' => 'v750',
'veri' => 'veri',
'vk-v' => 'vk-v',
'vk40' => 'vk40',
'vk50' => 'vk50',
'vk52' => 'vk52',
'vk53' => 'vk53',
'vm40' => 'vm40',
'vx98' => 'vx98',
'virg' => 'virg',
'vite' => 'vite',
'voda' => 'voda',
'vulc' => 'vulc',
'wapj' => 'wapj',
'wapp' => 'wapp',
'wapu' => 'wapu',
'wapm' => 'wapm',
'wig ' => 'wig ',
'wapi' => 'wapi',
'wapr' => 'wapr',
'wapv' => 'wapv',
'wapy' => 'wapy',
'wapa' => 'wapa',
'waps' => 'waps',
'wapt' => 'wapt',
'winc' => 'winc',
'winw' => 'winw',
'wonu' => 'wonu',
'x700' => 'x700',
'xda2' => 'xda2',
'xdag' => 'xdag',
'yas-' => 'yas-',
'your' => 'your',
'zte-' => 'zte-',
'zeto' => 'zeto',
'acs-' => 'acs-',
'alav' => 'alav',
'alca' => 'alca',
'amoi' => 'amoi',
'aste' => 'aste',
'audi' => 'audi',
'avan' => 'avan',
'benq' => 'benq',
'bird' => 'bird',
'blac' => 'blac',
'blaz' => 'blaz',
'brew' => 'brew',
'brvw' => 'brvw',
'bumb' => 'bumb',
'ccwa' => 'ccwa',
'cell' => 'cell',
'cldc' => 'cldc',
'cmd-' => 'cmd-',
'dang' => 'dang',
'doco' => 'doco',
'eml2' => 'eml2',
'eric' => 'eric',
'fetc' => 'fetc',
'hipt' => 'hipt',
'http' => 'http',
'ibro' => 'ibro',
'idea' => 'idea',
'ikom' => 'ikom',
'inno' => 'inno',
'ipaq' => 'ipaq',
'jbro' => 'jbro',
'jemu' => 'jemu',
'java' => 'java',
'jigs' => 'jigs',
'kddi' => 'kddi',
'keji' => 'keji',
'kyoc' => 'kyoc',
'kyok' => 'kyok',
'leno' => 'leno',
'lg-c' => 'lg-c',
'lg-d' => 'lg-d',
'lg-g' => 'lg-g',
'lge-' => 'lge-',
'libw' => 'libw',
'm-cr' => 'm-cr',
'maui' => 'maui',
'maxo' => 'maxo',
'midp' => 'midp',
'mits' => 'mits',
'mmef' => 'mmef',
'mobi' => 'mobi',
'mot-' => 'mot-',
'moto' => 'moto',
'mwbp' => 'mwbp',
'mywa' => 'mywa',
'nec-' => 'nec-',
'newt' => 'newt',
'nok6' => 'nok6',
'noki' => 'noki',
'o2im' => 'o2im',
'opwv' => 'opwv',
'palm' => 'palm',
'pana' => 'pana',
'pant' => 'pant',
'pdxg' => 'pdxg',
'phil' => 'phil',
'play' => 'play',
'pluc' => 'pluc',
'port' => 'port',
'prox' => 'prox',
'qtek' => 'qtek',
'qwap' => 'qwap',
'rozo' => 'rozo',
'sage' => 'sage',
'sama' => 'sama',
'sams' => 'sams',
'sany' => 'sany',
'sch-' => 'sch-',
'sec-' => 'sec-',
'send' => 'send',
'seri' => 'seri',
'sgh-' => 'sgh-',
'shar' => 'shar',
'sie-' => 'sie-',
'siem' => 'siem',
'smal' => 'smal',
'smar' => 'smar',
'sony' => 'sony',
'sph-' => 'sph-',
'symb' => 'symb',
't-mo' => 't-mo',
'teli' => 'teli',
'tim-' => 'tim-',
'tosh' => 'tosh',
'treo' => 'treo',
'tsm-' => 'tsm-',
'upg1' => 'upg1',
'upsi' => 'upsi',
'vk-v' => 'vk-v',
'voda' => 'voda',
'vx52' => 'vx52',
'vx53' => 'vx53',
'vx60' => 'vx60',
'vx61' => 'vx61',
'vx70' => 'vx70',
'vx80' => 'vx80',
'vx81' => 'vx81',
'vx83' => 'vx83',
'vx85' => 'vx85',
'wap-' => 'wap-',
'wapa' => 'wapa',
'wapi' => 'wapi',
'wapp' => 'wapp',
'wapr' => 'wapr',
'webc' => 'webc',
'whit' => 'whit',
'winw' => 'winw',
'wmlb' => 'wmlb',
'xda-' => 'xda-',
)):
// check against a list of trimmed user agents to see if we find a match
if (!ereg("w3c_css_validator", strtolower($user_agent))) {
$mobile_browser = array(
'type' => 'mobile',
'group' => '',
);
// set mobile browser to TRUE
}
break;
}
// ends the switch
$result = $mobile_browser;
return $result;
}
/**
* Detection of the site type . the values comes out the configuration form.
*/
function mobile_tools_is_mobile_site() {
$site_detection = variable_get('mobile-tools-site-type-detection', 'mobile_tools');
drupal_load('module', $site_detection);
if ($site_detection == 'mobile_tools') {
return _mobile_tools_site_detection();
}
else {
return module_invoke($site_detection, 'is_mobile_site');
}
}
function _mobile_tools_site_detection() {
global $base_url;
// Check if $_SERVER variables are set if not, just return desktop... Still unclear what best solution is:
if (!isset($_SERVER['HTTP_HOST']) && !isset($_SERVER['SERVER_NAME'])) {
return 'desktop';
}
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];
// first check if the url is a m.* or .mobi url. This is robuts
$server_domain_elements = explode('.', $host);
if (count($server_domain_elements) > 0) {
if ($server_domain_elements[0] == 'm') {
// check for m.* domain
return 'mobile';
}
if ($server_domain_elements[count($server_domain_elements) - 1] == 'mobi') {
// check for *.mobi
return 'mobile';
}
}
// If this doesn't return an answer, we will have to do a comparison of the mobile and desktop url!
$mobile = variable_get('mobile_tools_mobile_url', mobile_tools_create_mobile_url($base_url));
$mobile_url = parse_url($mobile);
$mobile_url['host'] = mobile_tools_prepare_url($mobile_url['host']);
$desktop = variable_get('mobile_tools_desktop_url', $base_url);
$desktop_url = parse_url($desktop);
$desktop_url['host'] = mobile_tools_prepare_url($desktop_url['host']);
if (!array_key_exists('path', $desktop_url)) {
$desktop_url['path'] = '';
}
if (!array_key_exists('path', $mobile_url)) {
$mobile_url['path'] = '';
}
// If $_SERVER['HTTP_HOST'] is not set just return desktop
if (!isset($_SERVER['HTTP_HOST'])) {
return 'desktop';
}
$server_name = mobile_tools_prepare_url($_SERVER['HTTP_HOST']);
// Check domain first
if ($mobile_url['host'] == $server_name && $desktop_url['host'] != $server_name) {
return 'mobile';
}
elseif ($mobile_url['host'] != $server_name && $desktop_url['host'] == $server_name) {
return 'desktop';
}
// find longest url
$longest_url = strlen($mobile) > strlen($desktop) ? $mobile : $desktop;
$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
$uri = $protocol . $_SERVER['HTTP_HOST'] . request_uri();
$pos = strpos($uri, preg_replace('{/$}', '', $longest_url));
if ($pos === FALSE) {
return $longest_url == $mobile ? 'desktop' : 'mobile';
}
else {
return $longest_url == $mobile ? 'mobile' : 'desktop';
}
}
/**
* Calling the device groups, check first if third party module registered
* for doing the device detection
* @return $groups
* Array containing the device group detected by this module
*/
function mobile_tools_device_groups() {
$device_detection = variable_get('mobile-tools-device-detection', 'mobile_tools');
if ($device_detection != 'mobile_tools') {
return module_invoke($device_detection, 'device_groups');
}
else {
return _mobile_tools_device_groups();
}
}
/**
* Mobile Tools implementation of the hook_device_groups()
* This function returns the different device groups where this module can make a distinction for. This can be used
* to select different themes for different device groups.
*/
function _mobile_tools_device_groups() {
return array(
'iphone' => 'iPhone',
'ipod' => 'iPod',
'ipad' => 'iPad',
'android' => 'Android',
'opera_mini' => 'Opera Mini',
'blackberry' => 'BlackBerry',
);
}
/**
* Implementation of hook_devicecapability()
* This default implementation invokes the responsible module
*/
function mobile_tools_devicecapability($capability) {
return module_invoke(variable_get('mobile-tools-device-capability', 'wurfl'), 'devicecapability', $capability);
}
/**
* This function does some kind of normalisation of the urls when there is no subdomain available in the url
* e.g. domain.com becomes www.domain.com . this is because sometimes both www.domain.com and domain.com are the same
*/
function mobile_tools_prepare_url($url) {
$_url = parse_url($url);
$_url = $url['host'];
$_url = explode(".", $_url);
if (count($_url) == 2) {
return 'www' . implode(".", $_url);
}
else {
return $url;
}
}
/**
* Creation of the redirect url. Special care to create the correct url that will
* cause the Global Redirect module not to redirect!
*/
function mobile_tools_get_redirect_url() {
include_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
// special Siruna delimitor
// collect query parameters
if (drupal_is_front_page()) {
return variable_get('mobile_tools_mobile_url', '');
}
$query = array();
foreach ($_GET as $key => $value) {
if ($key != 'q') {
$query[] = $key . '=' . $value;
}
}
$query = count($query) > 0 ? implode('&', $query) : '';
//create the path and reassemble
$base = preg_replace('{/$}', '', variable_get('mobile_tools_mobile_url', ''));
$url = url($base . '/' . $_GET['q'], array(
'query' => $query,
));
return $url;
}
/**
* Helper function to assist in making a mobile url (m.*) from a given url
*
* @parm $url
* orginal url
* @return
* the mobile url
*/
function mobile_tools_create_mobile_url($url) {
$url_parsed = parse_url($url);
if (!array_key_exists('path', $url_parsed)) {
$url_parsed['path'] = "";
}
$url = $url_parsed['host'];
$url = explode('.', $url);
if (count($url) == 3) {
$url[0] = 'm';
return 'http://' . implode('.', $url) . $url_parsed['path'];
}
elseif (count($url) == 2) {
return 'http://m.' . implode('.', $url) . $url_parsed['path'];
}
else {
return 'http://' . implode('.', $url) . $url_parsed['path'] . '/mobile';
}
}
/**
* Alteration to global setting form
*/
function mobile_tools_form_alter(&$form, $form_state, $form_id) {
switch ($form_id) {
case 'user_admin_role':
if (variable_get('mobile_tools_enable_roles', 0)) {
$query = "SELECT COUNT(*) as count FROM {mobile_tools_roles_relations} WHERE mrid = %d";
$result = db_query($query, arg(4));
$item = db_fetch_object($result);
if (isset($item)) {
if ($item->count == 0) {
$form['mobile_tools_configure_role_' . arg(4)] = array(
'#type' => 'checkbox',
'#title' => t('Create a mobile context for this user role'),
'#default_value' => TRUE,
'#description' => t('check if you want to add a mobile context to this role. Adding a mobile context will result in the creation of a new role that will be assigned to the user when the site is beeing mobilized. When unchecking all configurations will be lost for that role.'),
);
$form['mobile_tools_role_type'] = array(
'#type' => 'hidden',
'#value' => 'desktop',
);
}
else {
$form['mobile_tools_role_type'] = array(
'#type' => 'hidden',
'#value' => 'mobile',
);
}
$form['#submit'][] = 'mobile_tools_roles_configuration_submit';
}
}
break;
case 'user_profile_form':
if (variable_get('mobile_tools_enable_roles', 0)) {
// We make sure that the mobile roles are not being displayed
$mobile_roles = mobile_tools_mobile_user_roles();
foreach ($mobile_roles as $rid => $role) {
unset($form['account']['roles']['#options'][$rid]);
}
}
break;
case 'node_configure':
$form['default_nodes_main_mobile'] = array(
'#type' => 'select',
'#title' => t('Number of posts on main page for the mobile version'),
'#default_value' => variable_get('default_nodes_main_mobile', variable_get('default_nodes_main')),
'#options' => array(
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7,
8 => 8,
9 => 9,
10 => 10,
15 => 15,
20 => 20,
25 => 25,
30 => 30,
),
'#description' => t('The default maximum number of posts to display per page on overview pages such as the main page (on Mobile).'),
);
break;
case 'system_site_information_settings':
$form['site_frontpage_mobile'] = array(
'#type' => 'textfield',
'#title' => t('Choose another frontpage for mobile visitors.'),
'#default_value' => variable_get('site_frontpage_mobile', variable_get('site_frontpage', 'node')),
'#description' => t('If you want a different page as the frontpage of your site for mobile users, specify it here.'),
'#weight' => 1,
);
break;
}
}
/**
* copy of drupal_goto, since this is called in hook_boot, while the function is not yet available
*/
function mobile_tools_goto($path = '', $query = NULL, $fragment = NULL, $http_response_code = 302) {
$url = $path;
// Make the given path or URL absolute
if (!preg_match('/^[a-z]+:\\/\\//', $url)) {
global $base_url;
$url = $base_url . '/' . $url;
}
$url .= empty($query) ? '' : '?' . $query;
$url .= empty($fragment) ? '' : '#' . $fragment;
// Remove newlines from the URL to avoid header injection attacks.
$url = str_replace(array(
"\n",
"\r",
), '', $url);
// Before the redirect, allow modules to react to the end of the page request.
bootstrap_invoke_all('exit');
// Even though session_write_close() is registered as a shutdown function, we
// need all session data written to the database before redirecting.
session_write_close();
header('Location: ' . $url, TRUE, $http_response_code);
// 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.
exit;
}
/**
* Implementation of hook_ctools_plugin_directory() to let the system know
* we implement access plugins.
*/
function mobile_tools_ctools_plugin_directory($module, $plugin) {
if ($plugin == 'access') {
return 'plugins/' . $plugin;
}
}
/**
* Adding support for Node Displays build modes
* See http://drupal.org/project/nd
*/
/**
* Implementation of hook_nodeapi
*/
function mobile_tools_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
if ($op == 'load' && mobile_tools_is_mobile_site() && variable_get('mobile_tools_enable_build_mode', 0)) {
$node->build_mode = 'mobile_tools';
}
}
/**
* Implementation of hook_content_build_modes
*/
function mobile_tools_content_build_modes() {
return array(
'mobile_tools' => array(
'title' => t('Mobile theme'),
'build modes' => array(
'mobile_tools' => array(
'title' => t('Mobile theme'),
'views style' => TRUE,
),
),
),
);
}
Functions
Name | Description |
---|---|
mobile_tools_block | Implementation of hook_block() Provides the blocks that can be used to show a message to the user to go to the mobile or desktop version. |
mobile_tools_block_message | Helper function returning the configurable message for the notification |
mobile_tools_boot | Implementation of hook_boot(). Hook boot is called for both anonymous users and logged in users |
mobile_tools_content_build_modes | Implementation of hook_content_build_modes |
mobile_tools_create_mobile_url | Helper function to assist in making a mobile url (m.*) from a given url |
mobile_tools_ctools_plugin_directory | Implementation of hook_ctools_plugin_directory() to let the system know we implement access plugins. |
mobile_tools_devicecapability | Implementation of hook_devicecapability() This default implementation invokes the responsible module |
mobile_tools_device_groups | Calling the device groups, check first if third party module registered for doing the device detection |
mobile_tools_device_redirect | Being called in the hook_boot() implementation This function is in charge of redirection or displaying a notification |
mobile_tools_form_alter | Alteration to global setting form |
mobile_tools_get_device | Get $device object. Check if the 'device' argument is present or a cookie is set to overwrite the device: |
mobile_tools_get_redirect_url | Creation of the redirect url. Special care to create the correct url that will cause the Global Redirect module not to redirect! |
mobile_tools_goto | copy of drupal_goto, since this is called in hook_boot, while the function is not yet available |
mobile_tools_help | Implementation of hook_help($section). |
mobile_tools_is_mobile_device | Detect the device |
mobile_tools_is_mobile_site | Detection of the site type . the values comes out the configuration form. |
mobile_tools_menu | Implementation of hook_menu(). |
mobile_tools_nodeapi | Implementation of hook_nodeapi |
mobile_tools_perm | Implementation of hook_perm(). |
mobile_tools_prepare_url | This function does some kind of normalisation of the urls when there is no subdomain available in the url e.g. domain.com becomes www.domain.com . this is because sometimes both www.domain.com and domain.com are the same |
mobile_tools_switch_theme | Being called in the hook_boot() implementation This function is in charge of changing to the mobile theme |
_mobile_tools_device_groups | Mobile Tools implementation of the hook_device_groups() This function returns the different device groups where this module can make a distinction for. This can be used to select different themes for different device groups. |
_mobile_tools_is_mobile_device | Default implementation of hook_is_mobile_device() |
_mobile_tools_site_detection |
Constants
Name | Description |
---|---|
DESKTOP_NOTIFICATION | |
MOBILE_NOTIFICATION |