'subdomain_view_homepage', 'access callback' => TRUE, ); $items['admin/settings/subdomain'] = array( 'title' => t('Subdomain Settings'), 'description' => t('Configure subdomain settings.'), 'page callback' => 'subdomain_admin', 'page arguments' => array('subdomain_admin_settings'), 'access arguments' => array('administer site configuration'), 'file' => 'includes/subdomain.admin.inc', ); $items['subdomain/validate'] = array( 'page callback' => 'subdomain_js_validate', 'access callback' => TRUE, ); $items['subdomain/test'] = array( 'page callback' => '_subdomain_test_request', 'access callback' => TRUE, 'file' => 'includes/subdomain.admin.inc' ); return $items; } function subdomain_view_homepage() { $output = ''; if (subdomain()->home == 'view') { // Build argument array for view $args = arg(); // Remove "subdomain/homepage" portions of path array_shift($args); array_shift($args); // Load and execute view $view = views_get_view(subdomain()->view); $output = $view->preview('default', $args); drupal_set_title($view->get_title()); } return $output; } /** * Implementation of hook_form_alter(). */ function subdomain_form_alter(&$form, $form_state, $form_id) { // Add subdomain field (if necessary) to appropriate entry form if (subdomain()->is_entry_form($form_id)) { subdomain()->entry_form_alter($form, $form_id); } } /** * Inbound URL rewrite helper * If host includes subdomain, rewrite URI and internal path if necessary */ function subdomain_url_inbound_alter(&$result, $path, $path_language) { static $executed = FALSE; // Only investigate URL on 1st execution if (!$executed) { $executed = TRUE; // Fetch subdomain ID if ($subdomain_value = subdomain_get_current_subdomain()) { // Do nothing if subdomain is "www" or reserved if (variable_get('subdomain_prepend_www', TRUE) && $subdomain_value == 'www' || in_array($subdomain_value, subdomain_get_reserved_subdomains())) { return; } // Try and find subdomain record and associated Drupal object $subdomain = subdomain()->load($subdomain_value, 'subdomain'); if ($subdomain) { $sid = $subdomain->sid; } // If subdomain doesn't exist, send user to page not found elseif ($subdomain_value != SUBDOMAIN_TEST_SUBDOMAIN) { $result = $_REQUEST['q'] = 'subdomain/notfound/'. $_SERVER['HTTP_HOST'] .'/'. $path; } } // If subdomain and no path, rewrite to subdomain homepage if (isset($sid) && !isset($_REQUEST['q'])) { if (subdomain()->home == 'default') { $result = $_REQUEST['q'] = subdomain()->base_path($sid); } else { $result = $_REQUEST['q'] = "subdomain/homepage/$sid"; } } elseif ($nid = _subdomain_id_from_path('nid', $result)) { // If the path is a node path for the current node-based subdomain (e.g. an og group edit path: node/%/edit), do nothing if (subdomain()->type() == 'node' && isset($sid) && $nid == $sid) { // do nothing } // If we're viewing a subdomain content path, ensure we're on the correct subdomain // Force PageNotFound if user attempting to view content on incorrect subdomain... elseif (subdomain_get_content_subdomain($nid, 'node') != subdomain_get_current_subdomain()) { $result = $_REQUEST['q'] = 'subdomain/notfound/'. $_SERVER['HTTP_HOST'] .'/'. $path; } } } } /** * Clear outbound URL cache */ function subdomain_url_outbound_cache_clear() { subdomain_url_outbound_alter($path, $options = array(), NULL, $clear_path_cache = TRUE); } /** * Outbound URL rewrite helper * Rewrite URLs: attach/remove subdmain as appropriate */ function subdomain_url_outbound_alter(&$path, &$options, $original_path, $clear_path_cache = FALSE) { // Cache outbound paths static $paths = array(); // Clear path cache (sometimes needed when new subdomains created - e.g. og) if ($clear_path_cache) { $paths = array(); } // Process path if not in cache if (!isset($paths[$original_path])) { $www = variable_get('subdomain_prepend_www', TRUE) ? 'www.' : ''; // If front page and we're on a subdomain, strip the subdomain if (($original_path == '' || $original_path == '') && subdomain_get_current_subdomain()) { $paths[$original_path]['path'] = $path; $paths[$original_path]['base_url'] = _subdomain_get_protocol() . $www . subdomain_get_domain(); } // Otherwise, process path and attach/remove subdomain if necessary else { // Determine subdomain if any from original_path, and alter path if necessary subdomain()->url_outbound_helper($subdomain, $path, $original_path, $is_system_path); // Cache $path in case it was altered $paths[$original_path]['path'] = $path; if ($is_system_path && subdomain_get_current_subdomain()) { $paths[$original_path]['base_url'] = _subdomain_get_protocol() . subdomain_get_current_subdomain() .'.'. subdomain_get_domain(); } elseif ($subdomain) { $paths[$original_path]['base_url'] = _subdomain_get_protocol() . $subdomain .'.'. subdomain_get_domain(); } else { $paths[$original_path]['base_url'] = _subdomain_get_protocol() . $www . subdomain_get_domain(); } } } // Set path and options $options['absolute'] = TRUE; $options['base_url'] = $paths[$original_path]['base_url']; $path = $paths[$original_path]['path']; } /** * Implementation of hook_user(). */ function subdomain_user($op, &$edit, &$account, $category = NULL) { if (subdomain()->mode == 'user') { switch ($op) { case 'load': $account->subdomain = subdomain()->load($account->uid); break; case 'insert': case 'update': subdomain()->save('user', $edit, $account->uid); break; case 'delete': subdomain_delete_subdomain($account->uid); break; case 'validate': // If new user, check if subdomain exists if (!isset($edit['_account']) && subdomain_exists($edit[subdomain()->form_field])) { form_set_error($field, t('Subdomain already taken. Please try a different one.')); } break; } } } /** * Implementation of hook_nodeapi(). */ function subdomain_nodeapi(&$node, $op, $teaser, $page) { switch ($op) { case 'load': $node->subdomain = subdomain()->lookup('node', $node, $node->nid); break; case 'insert': case 'update': subdomain()->save('node', $node, $node->nid); break; case 'delete': subdomain()->delete('node', $node, $node->nid); break; } } /** * Implementation of hook_taxonomy(). */ function subdomain_taxonomy($op, $type, $array) { if (subdomain()->mode == 'term' && $type == 'term') { switch ($op) { case 'insert': case 'update': subdomain()->save('term', $array, $array['tid']); break; case 'delete': subdomain_delete_subdomain($array['tid']); break; } } } function subdomain_exists($value) { $subdomain = subdomain()->load(subdomain_clean($value), 'subdomain'); return !empty($subdomain); } function subdomain_get_reserved_subdomains() { $reserved = variable_get('subdomain_reserved', ''); $reserved = strtolower(ereg_replace(chr(13) . chr(10), "\n", $reserved)); $reserved = explode("\n", $reserved); // Add internal test subdomain to reserved list array_unshift($reserved, SUBDOMAIN_TEST_SUBDOMAIN); return $reserved; } function subdomain_get_domain() { global $cookie_domain; return trim($cookie_domain, '.'); } /** * Removes everything except letters */ function subdomain_clean($raw) { return strtolower(preg_replace("/[^a-zA-Z-]/", "", $raw)); } /** * Returns current subdomain if any */ function subdomain_get_current_subdomain() { static $subdomain; if (!isset($subdomain)) { $subdomain_length = strpos($_SERVER['HTTP_HOST'], '.'. subdomain_get_domain()); $subdomain = substr($_SERVER['HTTP_HOST'], 0, $subdomain_length); if (variable_get('subdomain_prepend_www', TRUE) && $subdomain == 'www') { $subdomain = ''; } } return $subdomain; } function subdomain_get_subdomain($sid) { return db_fetch_object(db_query("SELECT * FROM {subdomain} WHERE sid = %d", $sid)); } function subdomain_get_content_subdomain($content_id, $type) { return db_result(db_query('SELECT subdomain FROM {subdomain_content} sn INNER JOIN {subdomain} s on sn.sid = s.sid WHERE content_id = %d AND type = "%s"', $content_id, $type)); } function subdomain_save_subdomain($id, $raw, $insert = FALSE) { $row->sid = $id; $row->subdomain = subdomain_clean($raw); drupal_write_record('subdomain', $row, $insert ? array() : array('sid')); } function subdomain_save_subdomain_content($content_id, $sid, $type = 'node') { // If a subdomain exists, add the content if (db_result(db_query("SELECT 1 FROM {subdomain} WHERE sid = %d", $sid))) { $row->sid = $sid; $row->content_id = $content_id; $row->type = $type; drupal_write_record('subdomain_content', $row); } } function subdomain_delete_subdomain($sid) { db_query('DELETE FROM {subdomain_content} WHERE sid = %d', $sid); db_query('DELETE FROM {subdomain} WHERE sid = %d', $sid); } function subdomain_delete_subdomain_cotent($content_id, $type = 'node') { db_query('DELETE FROM {subdomain_content} WHERE type = "%s" AND content_id = %d', $type, $content_id); } /** * JS form validation handler: checks whether subdomain already exists */ function subdomain_js_validate() { $subdomain = subdomain()->load(subdomain_clean($_GET['subdomain']), 'subdomain'); if ($subdomain) { // "Exists" if there's a record AND it's not the one currently being edited $exists = !$_GET['sid'] || $subdomain->sid != $_GET['sid']; } else { $exists = FALSE; } drupal_json(array('exists' => $exists)); exit; } /** * Checks whether protocol is https or http * Based on code from http://php.net/manual/en/reserved.variables.server.php#89306 */ function _subdomain_get_protocol() { if ($_SERVER['https'] == 1) /* Apache */ { return 'https://'; } elseif ($_SERVER['https'] == 'on') /* IIS */ { return 'https://'; } elseif ($_SERVER['SERVER_PORT'] == 443) /* others */ { return 'https://'; } else { return 'http://'; } } function _subdomain_id_from_path($type, $path) { // Borrowed from Domain Access: Advanced pattern matching, we find the node id based on token %n in the path string. static $paths; $default_paths = array( 'nid' => "node/%n\r\nnode/%n/edit\r\ncomment/reply/%n\r\nnode/add/book/parent/%n\r\nbook/export/html/%n\r\nnode/%n/outline", 'uid' => "user/%n\r\nuser/%n/edit", 'tid' => "taxonomy/term/%n", ); $id = NULL; if (!isset($paths[$type])) { $pathdata = variable_get('subdomain_'. $type .'_paths', $default_paths[$type]); $path_match = preg_replace('/(\r\n?|\n)/', '|', $pathdata); $paths[$type] = explode("|", $path_match); } $pattern = explode('/', $path); foreach ($paths[$type] as $match) { $match_array = explode('/', $match); $placeholder = array_search('%n', $match_array); if (isset($pattern[$placeholder])) { $match_array[$placeholder] = $pattern[$placeholder]; if (is_numeric($pattern[$placeholder]) && $match_array == $pattern) { $id = (int) $pattern[$placeholder]; break; } } } return $id; } function _subdomain_add_js_validation($selector, $sid = NULL) { drupal_add_js(array('subdomain' => array('selector' => $selector, 'sid' => $sid)), 'setting'); } function _subdomain_get_custom_form_field($default, $editable = FALSE) { if ($editable) { return array( '#type' => 'textfield', '#title' => t('Choose a subdomain'), '#description' => t('Letters and underscores only. Choose carefully, once set, this cannot be changed.'), '#required' => TRUE, '#weight' => -5, '#default_value' => $default, ); } else { return array( '#type' => 'item', '#title' => t('My homepage'), '#weight' => -5, '#value' => 'http://'. $default . subdomain_get_domain(), ); } }