domain_user.module

Tracking 5.x-1.x branch
  1. drupal
    1. 5 contributions/domain/domain_user/domain_user.module
    2. 6 contributions/domain/domain_user/domain_user.module

Creates unique subdomains for registered users.

Functions & methods

NameDescription
domain_user_configure_formFormsAPI
domain_user_disableImplement hook_disable()
domain_user_domainloadImplement hook_domainload()
domain_user_domainupdateImplement hook_domainupdate()
domain_user_domainviewImplement hook_domainview()
domain_user_enableImplement hook_enable()
domain_user_initImplement hook_init()
domain_user_lookupCheck to see if a user has created a domain record
domain_user_menuImplement hook_menu()
domain_user_permImplement hook_perm()
domain_user_rulesChecks for existing domains to create rules
domain_user_strip_charsTurn a user name into a domain-safe string.
domain_user_userImplement hook_user()

File

View source
  1. <?php
  2. /**
  3. * @defgroup domain_user Domain User: personal subdomains
  4. *
  5. * Creates unique subdomains for registered users.
  6. */
  7. /**
  8. * @file
  9. * Creates unique subdomains for registered users.
  10. *
  11. * @ingroup domain_user
  12. */
  13. /**
  14. * Implement hook_init()
  15. *
  16. * We have to do this because we cannot redirect on login.
  17. */
  18. function domain_user_init() {
  19. if (isset($_SESSION['domain_user'])) {
  20. $domain = domain_user_lookup($_SESSION['domain_user']);
  21. unset($_SESSION['domain_user']);
  22. domain_goto($domain);
  23. }
  24. }
  25. /**
  26. * Implement hook_menu()
  27. */
  28. function domain_user_menu($may_cache) {
  29. $items = array();
  30. if ($may_cache) {
  31. $items[] = array(
  32. 'title' => t('User domains'),
  33. 'path' => 'admin/build/domain/user',
  34. 'type' => MENU_LOCAL_TASK,
  35. 'access' => user_access('administer domains'),
  36. 'callback' => 'drupal_get_form',
  37. 'callback arguments' => array('domain_user_configure_form')
  38. );
  39. }
  40. return $items;
  41. }
  42. /**
  43. * Implement hook_perm()
  44. */
  45. function domain_user_perm() {
  46. return array('create personal domain');
  47. }
  48. /**
  49. * FormsAPI
  50. */
  51. function domain_user_configure_form() {
  52. drupal_set_title(t('User domain settings'));
  53. $form = array();
  54. $form['domain_user'] = array(
  55. '#type' => 'radios',
  56. '#title' => t('Module behavior'),
  57. '#options' => array(0 => t('Do not create domains for users'), 1 => t('Automatically create domains for new users'), 2 => t('Ask users if they would like to create a domain')),
  58. '#description' => t('Should subdomains be created when users register?'),
  59. '#default_value' => variable_get('domain_user', 0),
  60. );
  61. $form['domain_user_root'] = array(
  62. '#type' => 'textfield',
  63. '#title' => t('Root domain name'),
  64. '#size' => 40,
  65. '#maxlength' => 80,
  66. '#required' => TRUE,
  67. '#default_value' => variable_get('domain_user_root', variable_get('domain_root', '')),
  68. '#description' => t('The root domain to use for creating user domains, typically <em>example.com</em>. No http or slashes.
  69. <br /> When users create domains, their username will be added to the root domain to create a custom domain.
  70. <br /> For example, <em>user1.example.com</em> or <em>administrator.example.com</em>.')
  71. );
  72. $form['domain_user_scheme'] = array(
  73. '#type' => 'radios',
  74. '#title' => t('User Domain URL scheme'),
  75. '#options' => array('http' => 'http://', 'https' => 'https://'),
  76. '#default_value' => variable_get('domain_user_scheme', 'http'),
  77. '#description' => t('The URL scheme for accessing user domains.')
  78. );
  79. $form['domain_user_login'] = array(
  80. '#type' => 'radios',
  81. '#title' => t('User login behavior'),
  82. '#options' => array(1 => t('On login, go to personal domain'), 0 => t('Do not go to personal domain on login')),
  83. '#default_value' => variable_get('domain_user_login', 1),
  84. '#description' => t('The domain users should go to when they login to the site.')
  85. );
  86. if (module_exists('domain_prefix')) {
  87. $form['domain_user_prefixing'] = array(
  88. '#type' => 'radios',
  89. '#title' => t('Domain table prefixing'),
  90. '#options' => array(0 => t('Never create prefixed tabled for user domains'), 1 => t('Obey the settings in Domain Prefix')),
  91. '#description' => t('Should user domains have detabase talbes created?'),
  92. '#default_value' => variable_get('domain_user_prefixing', 0),
  93. );
  94. }
  95. // Show the rules for username restrictions
  96. $rules = domain_user_rules();
  97. if (!empty($rules)) {
  98. $output = '<ul>';
  99. foreach ($rules as $rule) {
  100. $output .= '<li>'. $rule .'</li>';
  101. }
  102. $output .= '</ul>';
  103. }
  104. $form['rules'] = array(
  105. '#type' => 'markup',
  106. '#weight' => 20,
  107. '#value' => '<br /><br />'. t('<h3>Reserved Usernames</h3><p>The following usernames cannot be registered, since they are used as unique subdomains:</p>') . $output,
  108. );
  109. return system_settings_form($form);
  110. }
  111. /**
  112. * Checks for existing domains to create rules
  113. *
  114. * @param $generate
  115. * A boolean flag indicating whether to generate {access} table entries based on
  116. * the current domain set. Default to TRUE.
  117. * @return
  118. * An array of reserved name strings or an empty array.
  119. */
  120. function domain_user_rules($generate = TRUE) {
  121. // Find domains that are not user domains. These are blacklisted in user rules.
  122. // We set the $reset flag to TRUE, to be sure we catch all changes.
  123. $domains = domain_domains(TRUE);
  124. $reserved = array();
  125. // Get the root user domain.
  126. $root = variable_get('domain_user_root', variable_get('domain_root', ''));
  127. foreach ($domains as $domain) {
  128. if ($domain['domain_id'] > 0 && !$domain['uid'] && !empty($root)) {
  129. // Chop the name of domains to find the username equivalent.
  130. $string = str_replace('.'. $root, '', $domain['subdomain']);
  131. // In this case, we do strip port protocols, since they make no sense as usernames.
  132. $str = explode(':', $string);
  133. $name_string = $str[0];
  134. $reserved[] = $name_string;
  135. if ($generate && !empty($name_string)) {
  136. $check = db_result(db_query("SELECT aid FROM {access} WHERE mask = '%s'", $name_string));
  137. if (!$check) {
  138. db_query("INSERT INTO {access} (mask, type, status) VALUES ('%s', '%s', %d)", $name_string, 'user', 0);
  139. }
  140. }
  141. }
  142. }
  143. return $reserved;
  144. }
  145. /**
  146. * Implement hook_enable()
  147. *
  148. * When the module is enabled, create the rules for existing domains.
  149. */
  150. function domain_user_enable() {
  151. domain_user_rules();
  152. }
  153. /**
  154. * Implement hook_disable()
  155. *
  156. * Deletes our user access masks.
  157. */
  158. function domain_user_disable() {
  159. $rules = domain_user_rules(FALSE);
  160. foreach ($rules as $rule) {
  161. db_query("DELETE FROM {access} WHERE mask = '%s'", $rule);
  162. }
  163. }
  164. /**
  165. * Implement hook_domainload()
  166. */
  167. function domain_user_domainload(&$domain) {
  168. // Zero is the default domain, and we don't want to invalidate it.
  169. if ($domain['domain_id'] > 0) {
  170. $data = db_fetch_array(db_query("SELECT du.uid, u.status FROM {domain_user} du INNER JOIN {users} u ON du.uid = u.uid WHERE du.domain_id = %d", $domain['domain_id']));
  171. if ($data['uid']) {
  172. $domain['uid'] = $data['uid'];
  173. }
  174. }
  175. }
  176. /**
  177. * Implement hook_user()
  178. */
  179. function domain_user_user($op, &$edit, &$account, $category = NULL) {
  180. switch ($op) {
  181. case 'view':
  182. $domain = domain_user_lookup($account->uid);
  183. if ($domain != -1) {
  184. $items['domain'] = array(
  185. 'title' => t(''),
  186. 'value' => l($domain['path'], $domain['path']),
  187. 'class' => ''
  188. );
  189. return array(t('Personal web site') => $items);
  190. }
  191. break;
  192. case 'register':
  193. case 'form':
  194. // This function will return -1 if no domain exists. If no user exists yet, assume -1.
  195. $domain = -1;
  196. if (isset($account->uid)) {
  197. $domain = domain_user_lookup($account->uid);
  198. }
  199. // New users throw E_ALL errors.
  200. $name = t('username');
  201. if (isset($account->name)) {
  202. // Sanitize the username according to the host RFC.
  203. $name = domain_user_strip_chars($account->name);
  204. }
  205. $default = domain_default();
  206. $root = variable_get('domain_user_root', $default['subdomain']);
  207. // If the user name is on the ban list, we do not create a domain.
  208. // TODO: Maybe we should set a message here.
  209. if ($domain == -1 && domain_lookup(NULL, $name .'.'. $root) == -1) {
  210. $create_domain = variable_get('domain_user', 0);
  211. if (user_access('create personal domain')) {
  212. if ($create_domain == 1 && !empty($root)) {
  213. $form['domain_user_domain']['domain_create_user'] = array(
  214. '#type' => 'value',
  215. '#value' => 1,
  216. );
  217. }
  218. else if ($create_domain == 2 && !empty($root)) {
  219. $form['domain_user_domain'] = array(
  220. '#type' => 'fieldset',
  221. '#title' => t('Personal web site'),
  222. '#collapsible' => TRUE,
  223. '#collapsed' => FALSE,
  224. '#weight' => 1
  225. );
  226. $form['domain_user_domain']['domain_create_user'] = array(
  227. '#type' => 'checkbox',
  228. '#return_value' => 1,
  229. '#title' => t('Yes, I want to create my own site at <b>!user.!site</b>', array('!user' => $name, '!site' => $root)),
  230. );
  231. }
  232. return $form;
  233. }
  234. }
  235. break;
  236. case 'insert':
  237. case 'update':
  238. // If we did not come from our expected form, do nothing.
  239. if (!isset($edit['domain_create_user'])) {
  240. return;
  241. }
  242. if (!empty($edit['domain_create_user']) && user_access('create personal domain', $account)) {
  243. $user_root = variable_get('domain_user_root', variable_get('domain_root', ''));
  244. $name = domain_user_strip_chars($account->name);
  245. $form_values['sitename'] = $account->name;
  246. $form_values['subdomain'] = $name .'.'. $user_root;
  247. $form_values['valid'] = $account->status;
  248. $form_values['user_submitted'] = TRUE;
  249. // This function will return -1 if no domain exists.
  250. $domain = domain_user_lookup($account->uid);
  251. if ($domain == -1) {
  252. // Set arguments to be passed to the form
  253. $arguments = array('user_submitted' => TRUE);
  254. // Include the form file.
  255. include_once(drupal_get_path('module', 'domain') .'/domain_admin.inc');
  256. // Set the scheme as needed.
  257. $form_values['domain_scheme'] = variable_get('domain_user_scheme', 'http');
  258. drupal_execute('domain_create_form', $form_values, $arguments);
  259. $domain = domain_lookup(NULL, $form_values['subdomain'], TRUE);
  260. if ($domain['domain_id']) {
  261. db_query("INSERT INTO {domain_user} VALUES (%d, %d)", $domain['domain_id'], $account->uid);
  262. $edit['domains'][] = $domain['domain_id'];
  263. drupal_set_message(t('Your personal URL is <a href="!url">!url</a>.', array('!url' => url($domain['path']))));
  264. }
  265. else {
  266. drupal_set_message(t('Your personal URL could not be created.'));
  267. }
  268. }
  269. // Set the user's default domain to their subdomain.
  270. if ($domain['domain_id']) {
  271. // If the user cannot assign domain editors, only allow their unique domain.
  272. if (!user_access('assign domain editors')) {
  273. $edit['domain_user'] = array();
  274. }
  275. $edit['domain_user'][$domain['domain_id']] = $domain['domain_id'];
  276. // If the user account is blocked, set the domain to invalid.
  277. if ($account->status == 0) {
  278. db_query("UPDATE {domain} SET valid = 0 WHERE domain_id = %d", $domain['domain_id']);
  279. }
  280. }
  281. }
  282. if ($edit['domain_create_user'] && !user_access('create personal domain', $account)) {
  283. drupal_set_message(t('Your personal URL could not be created.'));
  284. }
  285. // Throw away what we do not need.
  286. $edit['domain_create_user'] = NULL;
  287. $edit['domains'] = NULL;
  288. // Special case if the username has changed.
  289. if ($op == 'update' && $edit['name'] != $account->name) {
  290. $domain = domain_user_lookup($account->uid, TRUE);
  291. if ($domain != -1) {
  292. $user_root = variable_get('domain_user_root', variable_get('domain_root', ''));
  293. $name = domain_user_strip_chars($edit['name']);
  294. $string = $name .'.'. $user_root;
  295. db_query("UPDATE {domain} SET subdomain = '%s', sitename = '%s' WHERE domain_id = %d", $string, $edit['name'], $domain['domain_id']);
  296. }
  297. }
  298. break;
  299. case 'login':
  300. // If the user has a personal domain, take them there.
  301. $domain = domain_user_lookup($account->uid);
  302. if (variable_get('domain_user_login', 1) && $domain != -1) {
  303. // We cannot do a redirect on login, which forces us to use a $_SESSION variable.
  304. // Only store the uid here, no need to store extra data where it can get hijacked.
  305. $_SESSION['domain_user'] = $account->uid;
  306. }
  307. break;
  308. case 'delete':
  309. // Delete the record
  310. // Run the lookup before we delete the row!
  311. $domain = domain_user_lookup($account->uid);
  312. if ($domain != -1) {
  313. db_query("DELETE FROM {domain} WHERE domain_id = %d", $domain['domain_id']);
  314. // Let other modules act.
  315. module_invoke_all('domainupdate', 'delete', $domain);
  316. }
  317. break;
  318. }
  319. }
  320. /**
  321. * Turn a user name into a domain-safe string.
  322. *
  323. * @param $name
  324. * The user name to process.
  325. * @return
  326. * A string with only alphanumeric characters and dashes.
  327. */
  328. function domain_user_strip_chars($name) {
  329. // Only alphanumeric characters are allowed.
  330. $pattern = '/[^a-zA-Z0-9]/';
  331. $name = preg_replace($pattern, '-', $name);
  332. return strtolower($name);
  333. }
  334. /**
  335. * Implement hook_domainupdate()
  336. */
  337. function domain_user_domainupdate($op, $domain = array(), $edit = array()) {
  338. $root = variable_get('domain_user_root', variable_get('domain_root', ''));
  339. switch ($op) {
  340. case 'update':
  341. // If these are different, then we must delete a row from {access}.
  342. if ($domain['subdomain'] != $edit['subdomain']) {
  343. $mask = str_replace('.'. $root, '', $domain['subdomain']);
  344. db_query("DELETE FROM {access} WHERE mask = '%s'", $mask);
  345. }
  346. domain_user_rules();
  347. break;
  348. case 'delete':
  349. // Delete from {domain_user}
  350. db_query("DELETE FROM {domain_user} WHERE domain_id = %d", $domain['domain_id']);
  351. // Delete from the access rules.
  352. $user_root = variable_get('domain_user_root', variable_get('domain_root', ''));
  353. $mask = str_replace('.'. $user_root, '', $domain['subdomain']);
  354. db_query("DELETE FROM {access} WHERE mask = '%s'", $mask);
  355. break;
  356. }
  357. }
  358. /**
  359. * Check to see if a user has created a domain record
  360. *
  361. * @param $uid
  362. * The user id of the domain to be checked. Optional.
  363. * @param $name
  364. * The username of the domain to be checked. Optional.
  365. * @param $domain_id
  366. * The domain_id taken from {domain}. Optional.
  367. * @param $clear
  368. * A boolean flag to clear the static variable if necessary. Not used. Here for consistency.
  369. */
  370. function domain_user_lookup($uid = NULL, $name = NULL, $domain_id = NULL, $clear = FALSE) {
  371. if ($uid) {
  372. $id = db_result(db_query("SELECT domain_id FROM {domain_user} WHERE uid = %d", $uid));
  373. }
  374. else if ($name) {
  375. $id = db_result(db_query("SELECT du.domain_id FROM {domain_user} du INNER JOIN {users} u ON du.uid = u.uid WHERE u.name = '%s'", $name));
  376. }
  377. else if ($domain_id) {
  378. $id = db_result(db_query("SELECT domain_id FROM {domain_user} WHERE domain_id = %d", $domain_id));
  379. }
  380. if ($id) {
  381. $return = domain_lookup($id);
  382. }
  383. else {
  384. $return = -1;
  385. }
  386. return $return;
  387. }
  388. /**
  389. * Implement hook_domainview()
  390. */
  391. function domain_user_domainview($op, $domain = array()) {
  392. switch ($op) {
  393. case 'header':
  394. return array(array('data' => t('User'), 'field' => 'du.uid'));
  395. break;
  396. case 'select':
  397. return 'du.uid';
  398. case 'join':
  399. return "LEFT JOIN {domain_user} du ON du.domain_id = d.domain_id";
  400. break;
  401. case 'data':
  402. if ($domain['uid']) {
  403. $account = user_load(array('uid' => $domain['uid']));
  404. return l($account->name, 'user/'. $account->uid);
  405. }
  406. break;
  407. }
  408. }

Related topics