hosting_site.module

Contains hook implementations for Hosting site module.

Functions

Namesort descending Description
hosting_get_sites_by_status Retrieve sites on a specific platform, with a specific status
hosting_get_site_by_url Retrieve a node based on the url
hosting_site_add_by_platform Page callback for Site add by platform.
hosting_site_add_by_platform_access Access callback for Site add by platform.
hosting_site_allow_domain Implements hook_allow_domain().
hosting_site_backup_action Callback for site backup action.
hosting_site_block_view_alter Implements hook_block_view_alter().
hosting_site_client_admin_block_visibility Control block visibility.
hosting_site_client_list_block_visibility Control block visibility.
hosting_site_count Returns a count of sites.
hosting_site_delete_action Callback for site delete action.
hosting_site_disable_action Callback for site disable action.
hosting_site_enable_action Callback for site enable action.
hosting_site_get_port Retrieve the port the site will be available on, so we can redirect.
hosting_site_goto Menu callback to go to your site.
hosting_site_hosting_tasks Implements hook_hosting_tasks().
hosting_site_menu Implements hook_menu().
hosting_site_node_access Implements hook_node_access().
hosting_site_op_login_reset Callback for site login reset action.
hosting_site_permission Implements hook_permission().
hosting_site_profile_block_visibility Control block visibility.
hosting_site_status_codes Define the status type labels and classes.
hosting_site_task_status @todo Please document this function.
hosting_site_theme Implements hook_theme().
hosting_site_verify_action Callback for site verify action.
hosting_site_views_api Views integration.
hosting_site_wildcard_load Menu wildcard loader callback.
theme_hosting_site_goto_link Theme function for site link.
theme_hosting_site_profile Theme function for install profile item.
_hosting_site_form_check
_hosting_site_goto_link Generate a link allowing the user to log into their new site, or simply go to the site front page if the link has expired.
_hosting_site_list_class Define the classes that correspond to the site status.
_hosting_site_status Define the status types of a site
_hosting_site_url Get site's URL.

Constants

Namesort descending Description
HOSTING_SITE_DELETED This site is deleted from the backend.
HOSTING_SITE_DISABLED This site is disabled.
HOSTING_SITE_ENABLED This site is created and enabled in the backend.
HOSTING_SITE_QUEUED This site is queued for creation.

File

site/hosting_site.module
View source
  1. <?php
  2. /**
  3. * @file
  4. * Contains hook implementations for Hosting site module.
  5. */
  6. /**
  7. * This site is deleted from the backend.
  8. */
  9. define('HOSTING_SITE_DELETED', -2);
  10. /**
  11. * This site is disabled.
  12. */
  13. define('HOSTING_SITE_DISABLED', -1);
  14. /**
  15. * This site is queued for creation.
  16. */
  17. define('HOSTING_SITE_QUEUED', 0);
  18. /**
  19. * This site is created and enabled in the backend.
  20. */
  21. define('HOSTING_SITE_ENABLED', 1);
  22. include_once 'hosting_site.nodeapi.inc';
  23. include_once 'hosting_site.form.inc';
  24. include_once 'hosting_site.backups.inc';
  25. //Conditonally include site quotas
  26. if (module_exists('hosting_quota')) {
  27. include_once 'hosting_site.quota.inc';
  28. }
  29. /**
  30. * Implements hook_menu().
  31. */
  32. function hosting_site_menu() {
  33. $items = array();
  34. $items['hosting/sites/list'] = array(
  35. 'title' => 'List',
  36. 'type' => MENU_DEFAULT_LOCAL_TASK,
  37. 'weight' => -10,
  38. );
  39. $items['hosting/sites/add'] = array(
  40. 'title' => 'Add site',
  41. 'type' => MENU_LOCAL_TASK,
  42. 'page callback' => 'drupal_goto',
  43. 'page arguments' => array('node/add/site'),
  44. 'access callback' => 'node_access',
  45. 'access arguments' => array('create', 'site'),
  46. );
  47. $items['node/%node/platform-add-site'] = array(
  48. 'title' => 'Add site',
  49. 'type' => MENU_LOCAL_TASK,
  50. 'page callback' => 'hosting_site_add_by_platform',
  51. 'page arguments' => array(1),
  52. 'access callback' => 'hosting_site_add_by_platform_access',
  53. 'access arguments' => array(1),
  54. );
  55. $items['hosting/hosting_site_form_check'] = array(
  56. 'page callback' => '_hosting_site_form_check',
  57. 'type' => MENU_CALLBACK,
  58. 'access arguments' => array('access content'),
  59. );
  60. $items['node/%node/goto_site'] = array(
  61. 'page callback' => 'hosting_site_goto',
  62. 'page arguments' => array(1),
  63. 'access callback' => 'node_access',
  64. 'access arguments' => array('view', 1),
  65. 'type' => MENU_CALLBACK,
  66. );
  67. return $items;
  68. }
  69. /**
  70. * Implements hook_theme().
  71. */
  72. function hosting_site_theme($existing, $type, $theme, $path) {
  73. $items = array();
  74. $items['hosting_site_profile'] = array(
  75. 'arguments' => array(
  76. 'profile' => NULL,
  77. 'html' => FALSE,
  78. ),
  79. );
  80. $items['hosting_site_goto_link'] = array(
  81. 'arguments' => array(
  82. 'title' => NULL,
  83. 'url' => NULL,
  84. ),
  85. );
  86. return $items;
  87. }
  88. function _hosting_site_form_check() {
  89. $platform = NULL;
  90. if (isset($_GET['platform'])) {
  91. $platform = $_GET['platform'];
  92. }
  93. drupal_json_output(
  94. hosting_site_available_options($_POST, $platform)
  95. );
  96. exit();
  97. }
  98. /**
  99. * Menu wildcard loader callback.
  100. *
  101. * Loads a hosting_site node.
  102. * @see hosting_task_menu().
  103. *
  104. * @param arg
  105. * Node's numeric nid
  106. *
  107. * @return object|bool
  108. */
  109. function hosting_site_wildcard_load($arg) {
  110. if (!is_numeric($arg)) {
  111. return FALSE;
  112. }
  113. if ($node = node_load($arg)) {
  114. if ($node->type == 'site') {
  115. return $node;
  116. }
  117. }
  118. return FALSE;
  119. }
  120. /**
  121. * Generate a link allowing the user to log into their new site, or simply
  122. * go to the site front page if the link has expired.
  123. */
  124. function _hosting_site_goto_link($node) {
  125. $cache = cache_get("hosting:site:" . $node->nid . ":login_link");
  126. if (user_access('create login-reset task') && $cache && (REQUEST_TIME < $cache->data['expire'])) {
  127. $title = t("Log in to !url", array('!url' => $node->title));
  128. }
  129. else {
  130. $title = t("Go to !url", array('!url' => $node->title));
  131. }
  132. $url = "node/" . $node->nid . "/goto_site";
  133. return theme('hosting_site_goto_link', array('title' => $title, 'url' => $url));
  134. }
  135. /**
  136. * Theme function for site link.
  137. */
  138. function theme_hosting_site_goto_link($variables) {
  139. $options['attributes']['class'] = 'hosting-goto-site-link';
  140. $options['attributes']['target'] = '_blank';
  141. return l($variables['title'], $variables['url'], $options);
  142. }
  143. /**
  144. * Menu callback to go to your site.
  145. *
  146. * This needs to be a callback because the link is only going to work once,
  147. * so this will remove the link from the cache and just redirect to the site
  148. * not the login page.
  149. */
  150. function hosting_site_goto($node) {
  151. $cid = "hosting:site:" . $node->nid . ":login_link";
  152. $cache = cache_get($cid);
  153. if (user_access('create login-reset task') && is_object($cache) && (REQUEST_TIME < $cache->data['expire'])) {
  154. $theurl = $cache->data['link'];
  155. cache_clear_all($cid, 'cache');
  156. }
  157. else {
  158. $theurl = _hosting_site_url($node);
  159. }
  160. drupal_goto($theurl);
  161. exit();
  162. }
  163. /**
  164. * Retrieve the port the site will be available on, so we can redirect.
  165. */
  166. function hosting_site_get_port($node) {
  167. $platform = node_load($node->platform);
  168. $server = node_load($platform->web_server);
  169. return $server->services['http']->port;
  170. }
  171. /**
  172. * Get site's URL.
  173. */
  174. function _hosting_site_url($node) {
  175. $schema = 'http';
  176. $port = NULL;
  177. $url = strtolower(trim($node->title));
  178. $platform = node_load($node->platform);
  179. $server = node_load($platform->web_server);
  180. if ($server->services['http']->has_port()) {
  181. $port = $server->services['http']->port;
  182. if ($port == 80) {
  183. $port = NULL;
  184. }
  185. }
  186. /**
  187. * This is part of the ssl feature, but is better to implement here.
  188. */
  189. if (isset($node->ssl_enabled) && ($node->ssl_enabled == 2)) {
  190. // this is a bit of a magic number, because we cant rely on the constant being available yet.
  191. // 2 == Only SSL is enabled.
  192. $schema = 'https';
  193. if ($server->services['http']->has_port()) {
  194. $port = $server->services['http']->ssl_port;
  195. if ($port == 443) {
  196. $port = NULL;
  197. }
  198. }
  199. }
  200. if (is_numeric($port)) {
  201. return "{$schema}://{$url}:{$port}";
  202. }
  203. return "{$schema}://{$url}";
  204. }
  205. /**
  206. * Implements hook_hosting_tasks().
  207. */
  208. function hosting_site_hosting_tasks() {
  209. $tasks = array();
  210. $tasks['site']['backup'] = array(
  211. 'title' => t('Backup'),
  212. 'description' => t('Generate a backup of this site that can be restored to at any time'),
  213. 'dialog' => TRUE,
  214. );
  215. $tasks['site']['restore'] = array(
  216. 'title' => t('Restore'),
  217. 'description' => t('Restore this site to a previous backup. A new backup will be created before this is attempted.'),
  218. 'dialog' => TRUE,
  219. );
  220. $tasks['site']['verify'] = array(
  221. 'title' => t('Verify'),
  222. 'description' => t('Confirm that the site has been correctly installed and regenerate all configuration files to match the hosting front end.'),
  223. 'provision_save' => TRUE,
  224. );
  225. $tasks['site']['disable'] = array(
  226. 'title' => t('Disable'),
  227. 'description' => t('Disabling this site will stop it from being accessible.
  228. It can be enabled again later.'),
  229. 'dialog' => TRUE,
  230. );
  231. $tasks['site']['enable'] = array(
  232. 'title' => t('Enable'),
  233. 'description' => t('Enabling this site will allow it to be accesible again.
  234. It may be disabled again if needed.'),
  235. );
  236. $tasks['site']['delete'] = array(
  237. 'title' => t('Delete'),
  238. 'description' => t('Deleting this site will completely remove it from the hosting system,
  239. but will keep the last backup available. This process can not be undone.
  240. Are you really sure you want to delete this site?'),
  241. 'dialog' => TRUE,
  242. );
  243. $tasks['site']['login-reset'] = array(
  244. 'title' => t('Reset password'),
  245. 'description' => t('Generate a one-time login reset url for this site.'),
  246. );
  247. $tasks['site']['backup-delete'] = array(
  248. 'title' => t('Delete backups'),
  249. 'description' => t('Delete one or more backup files of a site.'),
  250. 'dialog' => TRUE,
  251. );
  252. $tasks['site']['install'] = array(
  253. 'title' => t('Install'),
  254. 'description' => t('Install a site'),
  255. 'hidden' => TRUE,
  256. 'provision_save' => TRUE,
  257. );
  258. $tasks['site']['import'] = array(
  259. 'title' => t('Import'),
  260. 'description' => t('Import an existing site into Aegir'),
  261. 'hidden' => TRUE,
  262. );
  263. return $tasks;
  264. }
  265. /**
  266. * Implements hook_permission().
  267. */
  268. function hosting_site_permission() {
  269. return array(
  270. 'create site' => array(
  271. 'title' => t('create site'),
  272. ),
  273. 'view site' => array(
  274. 'title' => t('view site'),
  275. ),
  276. 'edit site' => array(
  277. 'title' => t('edit site'),
  278. ),
  279. 'delete site' => array(
  280. 'title' => t('delete site'),
  281. ),
  282. 'administer sites' => array(
  283. 'title' => t('administer sites'),
  284. ),
  285. );
  286. }
  287. /**
  288. * Implements hook_node_access().
  289. */
  290. function hosting_site_node_access($node, $op, $account) {
  291. if ($op != 'create' && hosting_feature('client')) {
  292. // we rely on hosting_client_node_grants() instead of global configuration
  293. return NULL; //@todo check this return value -> NODE_ACCESS_IGNORE?
  294. }
  295. if ($op == 'create' && user_access('create site', $account)) {
  296. return NODE_ACCESS_ALLOW;
  297. }
  298. if ($op == 'update' && user_access('edit site', $account)) {
  299. return NODE_ACCESS_ALLOW;
  300. }
  301. if ($op == 'delete' && user_access('delete site', $account)) {
  302. return NODE_ACCESS_ALLOW;
  303. }
  304. if ($op == 'view' && user_access('view site', $account)) {
  305. return NODE_ACCESS_ALLOW;
  306. }
  307. }
  308. /**
  309. * Callback for site backup action.
  310. *
  311. * @see: hosting_task_action_info().
  312. */
  313. function hosting_site_backup_action($node) {
  314. hosting_add_task($node->nid, 'backup');
  315. }
  316. /**
  317. * Callback for site verify action.
  318. *
  319. * @see: hosting_task_action_info().
  320. */
  321. function hosting_site_verify_action($node) {
  322. hosting_add_task($node->nid, 'verify');
  323. }
  324. /**
  325. * Callback for site disable action.
  326. *
  327. * @see: hosting_task_action_info().
  328. */
  329. function hosting_site_disable_action($node) {
  330. hosting_add_task($node->nid, 'disable');
  331. }
  332. /**
  333. * Callback for site enable action.
  334. *
  335. * @see: hosting_task_action_info().
  336. */
  337. function hosting_site_enable_action($node) {
  338. hosting_add_task($node->nid, 'enable');
  339. }
  340. /**
  341. * Callback for site delete action.
  342. *
  343. * @see: hosting_task_action_info().
  344. */
  345. function hosting_site_delete_action($node) {
  346. hosting_add_task($node->nid, 'delete');
  347. }
  348. /**
  349. * Callback for site login reset action.
  350. *
  351. * @see: hosting_task_action_info().
  352. */
  353. function hosting_site_op_login_reset($node) {
  354. hosting_add_task($node->nid, 'login-reset');
  355. }
  356. /**
  357. * Access callback for Site add by platform.
  358. */
  359. function hosting_site_add_by_platform_access($node) {
  360. return $node->type == 'platform' && $node->platform_status == HOSTING_PLATFORM_ENABLED && node_access('create', 'site');
  361. }
  362. /**
  363. * Page callback for Site add by platform.
  364. */
  365. function hosting_site_add_by_platform($node) {
  366. drupal_goto('node/add/site', array('query' => array('platform' => $node->nid)));
  367. }
  368. /**
  369. * Returns a count of sites.
  370. *
  371. * This is used by cron and statistics to batch the number of sites that are
  372. * processed with each call. It is also used to generate the 'site count' per
  373. * platform at /hosting/platforms
  374. *
  375. * By default it only counts enabled sites.
  376. *
  377. * Optionally can include an array of site statuses by which to consider in the
  378. * count.
  379. *
  380. * @param $platform
  381. * (optional) A platform nid to only count sites on that specific platform.
  382. * @param $statuses
  383. * (optional) An array of site statuses (defined by their constants) by which
  384. * to include such sites in the site count.
  385. *
  386. * @return
  387. * The number of sites matching the specified criteria.
  388. */
  389. function hosting_site_count($platform = NULL, $statuses = NULL) {
  390. if (is_null($statuses)) {
  391. $statuses = array(HOSTING_SITE_ENABLED);
  392. }
  393. $query = db_select('hosting_site')
  394. ->addTag('hosting_site_count')
  395. ->fields('hosting_site', array('nid'));
  396. if (count($statuses)) {
  397. $query->condition('status', $statuses);
  398. }
  399. if (!is_null($platform)) {
  400. $query->condition('platform', $platform);
  401. }
  402. return $query->countQuery()->execute()->fetchField();
  403. }
  404. /**
  405. * Retrieve sites on a specific platform, with a specific status
  406. */
  407. function hosting_get_sites_by_status($platform, $status) {
  408. $nodes = array();
  409. $result = db_query("SELECT nid FROM {hosting_site} WHERE platform = :platform AND status = :status", array(':platform' => $platform, ':status' => $status));
  410. while ($nid = $result->fetch()) {
  411. $nodes[$nid->nid] = node_load($nid->nid);
  412. }
  413. return $nodes;
  414. }
  415. /**
  416. * Retrieve a node based on the url
  417. */
  418. function hosting_get_site_by_url($url) {
  419. // If the Aliases feature is enabled, try and get the site by its alias too
  420. if (hosting_feature('alias')) {
  421. $nid = db_query("SELECT n.nid
  422. FROM {node} n
  423. JOIN {hosting_site} h
  424. ON n.nid = h.nid
  425. LEFT JOIN {hosting_site_alias} ha
  426. ON h.vid = ha.vid
  427. WHERE (n.title = :title OR ha.alias = :alias)
  428. AND n.type = :type
  429. AND NOT (h.status = :status)",
  430. array(
  431. ':title' => $url,
  432. ':alias' => $url,
  433. ':type' => 'site',
  434. ':status' => HOSTING_SITE_DELETED,
  435. ))->fetchField();
  436. }
  437. else {
  438. $nid = db_query("SELECT n.nid
  439. FROM {node} n
  440. JOIN {hosting_site} h
  441. ON n.nid = h.nid
  442. WHERE n.title = :title
  443. AND n.type = :type
  444. AND NOT (h.status = :status)",
  445. array(
  446. ':title' => $url,
  447. ':type' => 'site',
  448. ':status' => HOSTING_SITE_DELETED,
  449. ))->fetchField();
  450. }
  451. if ($nid) {
  452. return node_load($nid);
  453. }
  454. return FALSE;
  455. }
  456. /**
  457. * Define the status types of a site
  458. */
  459. function _hosting_site_status($node) {
  460. $status = (is_numeric($node)) ? $node : $node->site_status;
  461. $labels = hosting_site_status_codes('label');
  462. return $labels[$status];
  463. }
  464. /**
  465. * Define the status type labels and classes.
  466. *
  467. * @param $type
  468. * The type of status to return ('label' or 'class').
  469. *
  470. * @return array
  471. */
  472. function hosting_site_status_codes($type = NULL) {
  473. static $codes = array(
  474. HOSTING_SITE_QUEUED => array(
  475. 'label' => 'Queued',
  476. 'class' => 'hosting-queue',
  477. ),
  478. HOSTING_SITE_ENABLED => array(
  479. 'label' => 'Enabled',
  480. 'class' => 'hosting-success',
  481. ),
  482. HOSTING_SITE_DELETED => array(
  483. 'label' => 'Deleted',
  484. 'class' => 'hosting-error',
  485. ),
  486. HOSTING_SITE_DISABLED => array(
  487. 'label' => 'Disabled',
  488. 'class' => 'hosting-disable',
  489. ),
  490. );
  491. if (!is_null($type)) {
  492. // Return just the $type
  493. $return = array();
  494. foreach ($codes as $code => $types) {
  495. $return[$code] = $types[$type];
  496. }
  497. return $return;
  498. }
  499. else {
  500. // Return everything
  501. return $codes;
  502. }
  503. }
  504. /**
  505. * Implements hook_allow_domain().
  506. *
  507. * Disallow domains already used as any site's title/url, unless the site has
  508. * been deleted.
  509. *
  510. * @see hosting_domain_allowed()
  511. */
  512. function hosting_site_allow_domain($url, $params = array()) {
  513. $query = "SELECT COUNT(n.nid) FROM {node} n
  514. JOIN {hosting_site} h ON n.nid = h.nid
  515. WHERE type = 'site' AND n.title = :title AND h.status <> :status";
  516. $args[':title'] = $url;
  517. $args[':status'] = HOSTING_SITE_DELETED;
  518. if (isset($params['nid'])) {
  519. $query .= " AND n.nid <> :nid";
  520. $args[':nid'] = $params['nid'];
  521. }
  522. $result = !db_query($query, $args)->fetchField();
  523. return $result;
  524. }
  525. /**
  526. * @todo Please document this function.
  527. * @see http://drupal.org/node/1354
  528. */
  529. function hosting_site_task_status($nid) {
  530. return hosting_task_status_output('nid', $nid, 'install');
  531. }
  532. /**
  533. * Define the classes that correspond to the site status.
  534. * @see _hosting_site_status()
  535. */
  536. function _hosting_site_list_class($node, $verified = NULL) {
  537. $status = (is_numeric($node)) ? $node : $node->site_status;
  538. $classes = hosting_site_status_codes('class');
  539. if (($status == HOSTING_SITE_ENABLED) && ($verified <= 1)) {
  540. return 'hosting-warning';
  541. }
  542. return $classes[$status];
  543. }
  544. /**
  545. * Views integration.
  546. */
  547. function hosting_site_views_api() {
  548. return array(
  549. 'api' => 3,
  550. 'path' => drupal_get_path('module', 'hosting_site') . '/includes/views',
  551. );
  552. }
  553. /**
  554. * Theme function for install profile item.
  555. */
  556. function theme_hosting_site_profile($variables) {
  557. if ($variables['html']) {
  558. return "{$variables['profile']->title} <em>({$variables['profile']->short_name})</em>";
  559. }
  560. return "{$variables['profile']->title} ({$variables['profile']->short_name})";
  561. }
  562. /**
  563. * Control block visibility.
  564. */
  565. function hosting_site_client_list_block_visibility() {
  566. global $user;
  567. $node = menu_get_object();
  568. $menu_item = menu_get_item();
  569. if (!empty($node) && $menu_item['number_parts'] == 2) {
  570. return $node->type == 'client' && !user_access('administer clients', $user);
  571. }
  572. return FALSE;
  573. }
  574. /**
  575. * Control block visibility.
  576. */
  577. function hosting_site_client_admin_block_visibility() {
  578. global $user;
  579. $node = menu_get_object();
  580. $menu_item = menu_get_item();
  581. if (!empty($node) && $menu_item['number_parts'] == 2) {
  582. return $node->type == 'client' && user_access('administer clients', $user);
  583. }
  584. return FALSE;
  585. }
  586. /**
  587. * Control block visibility.
  588. */
  589. function hosting_site_profile_block_visibility() {
  590. $node = menu_get_object();
  591. $menu_item = menu_get_item();
  592. if (!empty($node) && $menu_item['number_parts'] == 2) {
  593. return $node->type == 'package' && $node->package_type == 'profile';
  594. }
  595. return FALSE;
  596. }
  597. /**
  598. * Implements hook_block_view_alter().
  599. *
  600. * @see: hosting_site_views_pre_build().
  601. */
  602. function hosting_site_block_view_alter(&$data, $block) {
  603. if ($block->delta =='hosting_site_list-block_sites') {
  604. if ($node = menu_get_object()) {
  605. // We only want to show a list of sites on a server with a database,
  606. // or on install profile package pages.
  607. if (($node->type == 'server' && !array_key_exists('db', $node->services))
  608. || ($node->type == 'package' && $node->package_type != 'profile')) {
  609. unset($data['subject']);
  610. unset($data['content']);
  611. }
  612. }
  613. }
  614. }