hosting_platform.module

Platform node type definition.

Functions

Namesort descending Description
hosting_nodeapi_platform_delete_revision Implements hook_nodeapi_TYPE_OP().
hosting_platform_delete Implements hook_delete().
hosting_platform_delete_action Callback for platform delete action.
hosting_platform_form Implements hook_form().
hosting_platform_form_alter Hide the delete button on platform nodes.
hosting_platform_form_platform_after_build After build callback for the hosting_platform_form.
hosting_platform_form_validate Form validation for platforms.
hosting_platform_hosting_site_site_list_filters Implements hook_hosting_site_site_list_filters().
hosting_platform_hosting_summary Implements hook_hosting_summary().
hosting_platform_hosting_tasks Implements hook_hosting_tasks().
hosting_platform_insert Implements hook_insert().
hosting_platform_load Implements hook_load().
hosting_platform_lock_action Callback for platform lock action.
hosting_platform_menu Implements hook_menu().
hosting_platform_node_access Implements hook_node_access(). @todo: switch to node access constants
hosting_platform_node_info Implements hook_node_info().
hosting_platform_path_exists Determine whether a given path has already been used with an existing platform.
hosting_platform_permission Implements hook_permission().
hosting_platform_unlock_action Callback for platform unlock action.
hosting_platform_update Implements hook_update().
hosting_platform_validate Implements hook_validate().
hosting_platform_verify_action Callback for platform verify action.
hosting_platform_view Implements hook_view().
hosting_platform_views_api Implements hook_views_api().
hosting_platform_wildcard_load Menu wildcard loader callback.
_hosting_get_enabled_platforms Helper function to get platforms that haven't been deleted or locked.
_hosting_get_locked_platforms Helper function to get platforms that have been locked.
_hosting_get_platforms Helper function to get platforms that haven't been deleted.
_hosting_platform_is_locked Helper function to check if a platform is locked.
_hosting_platform_list_class Define the classes that correspond to the platform status.
_hosting_platform_status Return the appropriate status label.
_hosting_platform_status_codes Helper function to map status codes to labels and classes.

Constants

Namesort descending Description
HOSTING_PLATFORM_DELETED This platform has been deleted.
HOSTING_PLATFORM_ENABLED This platform is created and enabled, sites may be deployed on it.
HOSTING_PLATFORM_LOCKED This platform has been locked, new sites will not be allowed to use it.
HOSTING_PLATFORM_QUEUED This platform has been queued for creation.

File

platform/hosting_platform.module
View source
  1. <?php
  2. /**
  3. * @file
  4. * Platform node type definition.
  5. */
  6. /**
  7. * This platform has been deleted.
  8. */
  9. define('HOSTING_PLATFORM_DELETED', -2);
  10. /**
  11. * This platform has been locked, new sites will not be allowed to use it.
  12. */
  13. define('HOSTING_PLATFORM_LOCKED', -1);
  14. /**
  15. * This platform has been queued for creation.
  16. */
  17. define('HOSTING_PLATFORM_QUEUED', 0);
  18. /**
  19. * This platform is created and enabled, sites may be deployed on it.
  20. */
  21. define('HOSTING_PLATFORM_ENABLED', 1);
  22. /**
  23. * Implements hook_menu().
  24. */
  25. function hosting_platform_menu() {
  26. $items = array();
  27. $items['hosting/platforms/list'] = array(
  28. 'title' => 'List',
  29. 'type' => MENU_DEFAULT_LOCAL_TASK,
  30. 'weight' => -10,
  31. );
  32. $items['hosting/platforms/add'] = array(
  33. 'title' => 'Add platform',
  34. 'type' => MENU_LOCAL_TASK,
  35. 'page callback' => 'drupal_goto',
  36. 'page arguments' => array('node/add/platform'),
  37. 'access callback' => 'node_access',
  38. 'access arguments' => array('create', 'platform'),
  39. );
  40. return $items;
  41. }
  42. /**
  43. * Implements hook_node_info().
  44. */
  45. function hosting_platform_node_info() {
  46. $types["platform"] = array(
  47. "type" => 'platform',
  48. "name" => 'Platform',
  49. 'base' => 'hosting_platform',
  50. "has_title" => TRUE,
  51. "title_label" => t('Name'),
  52. "description" => hosting_node_help("platform"),
  53. "has_body" => 0,
  54. "body_label" => '',
  55. "min_word_count" => 0,
  56. );
  57. return $types;
  58. }
  59. /**
  60. * Implements hook_hosting_tasks().
  61. */
  62. function hosting_platform_hosting_tasks() {
  63. $tasks = array();
  64. $tasks['platform']['verify'] = array(
  65. 'title' => t('Verify'),
  66. 'description' => t('Verify that the platform is correctly installed and working.'),
  67. 'weight' => 10,
  68. 'provision_save' => TRUE,
  69. );
  70. $tasks['platform']['delete'] = array(
  71. 'title' => t('Delete'),
  72. 'description' => t('Deleting this platform will completely remove it from the hosting system.
  73. This process can not be undone. It can not be performed if you have sites currently
  74. running on this platform.
  75. Are you really sure you want to delete this platform?'),
  76. 'weight' => 10,
  77. 'dialog' => TRUE,
  78. );
  79. $tasks['platform']['lock'] = array(
  80. 'title' => t('Lock'),
  81. 'description' => t('Locking this platform will not delete or disable it or its sites, but will
  82. prevent any new sites from being created on it. This may be useful when you have sites that
  83. cannot be migrated onto a newer platform, but you wish to prevent other users or clients
  84. from continuing to provision on this platform. The platform can be unlocked later.
  85. Are you really sure you want to lock this platform?'),
  86. 'weight' => 10,
  87. );
  88. $tasks['platform']['unlock'] = array(
  89. 'title' => t('Unlock'),
  90. 'description' => t('Unlocking this platform will allow sites to be provisioned on it.
  91. Are you really sure you want to unlock this platform?'),
  92. 'weight' => 10,
  93. );
  94. return $tasks;
  95. }
  96. /**
  97. * Implements hook_permission().
  98. */
  99. function hosting_platform_permission() {
  100. return array(
  101. 'administer platforms' => array(
  102. 'title' => t('administer platforms'),
  103. ),
  104. 'create platform' => array(
  105. 'title' => t('create platform'),
  106. ),
  107. 'view platform' => array(
  108. 'title' => t('view platform'),
  109. ),
  110. 'edit platform' => array(
  111. 'title' => t('edit platform'),
  112. ),
  113. 'delete platform' => array(
  114. 'title' => t('delete platform'),
  115. ),
  116. 'view locked platforms' => array(
  117. 'title' => t('view locked platforms'),
  118. ),
  119. 'create sites on locked platforms' => array(
  120. 'title' => t('create sites on locked platforms'),
  121. ),
  122. );
  123. }
  124. /**
  125. * Implements hook_node_access().
  126. * @todo: switch to node access constants
  127. */
  128. function hosting_platform_node_access($node, $op, $account) {
  129. if ($op != 'create' && hosting_feature('client')) {
  130. // We rely on hosting_client_node_grants() instead of global configuration.
  131. return NULL;
  132. }
  133. switch ($op) {
  134. case 'create':
  135. return user_access('create platform', $account);
  136. case 'update':
  137. return user_access('edit platform', $account);
  138. case 'view':
  139. return user_access('view platform', $account);
  140. }
  141. }
  142. /**
  143. * Callback for platform verify action.
  144. *
  145. * @see: hosting_task_action_info().
  146. */
  147. function hosting_platform_verify_action($node) {
  148. hosting_add_task($node->nid, 'verify');
  149. }
  150. /**
  151. * Callback for platform lock action.
  152. *
  153. * @see: hosting_task_action_info().
  154. */
  155. function hosting_platform_lock_action($node) {
  156. hosting_add_task($node->nid, 'lock');
  157. }
  158. /**
  159. * Callback for platform unlock action.
  160. *
  161. * @see: hosting_task_action_info().
  162. */
  163. function hosting_platform_unlock_action($node) {
  164. hosting_add_task($node->nid, 'unlock');
  165. }
  166. /**
  167. * Callback for platform delete action.
  168. *
  169. * @see: hosting_task_action_info().
  170. */
  171. function hosting_platform_delete_action($node) {
  172. hosting_add_task($node->nid, 'delete');
  173. }
  174. /**
  175. * Helper function to get platforms that haven't been deleted.
  176. *
  177. * @param int $web_server
  178. * Node ID of the server hosting this platform.
  179. * Default 0 indicates any web_server.
  180. */
  181. function _hosting_get_platforms($web_server = 0) {
  182. $return = array();
  183. $result = db_query("SELECT n.nid, n.title
  184. FROM {node} n
  185. LEFT JOIN {hosting_platform} h
  186. ON n.nid = h.nid
  187. WHERE n.type = :type
  188. AND n.status = :nstatus
  189. AND h.status <> :hstatus
  190. AND (h.web_server = :web_server OR :web_server = 0)
  191. ORDER BY n.title
  192. ", array(
  193. ':type' => 'platform',
  194. ':nstatus' => 1, //@todo: remove magic number?
  195. ':hstatus' => HOSTING_PLATFORM_DELETED,
  196. ':web_server' => $web_server,
  197. )
  198. );
  199. while ($platform = $result->fetch()) {
  200. $return[$platform->nid] = $platform->title;
  201. }
  202. return $return;
  203. }
  204. /**
  205. * Helper function to get platforms that haven't been deleted or locked.
  206. */
  207. function _hosting_get_enabled_platforms() {
  208. $return = array();
  209. $result = db_query("SELECT n.nid, n.title
  210. FROM {node} n
  211. LEFT JOIN {hosting_platform} h
  212. ON n.nid = h.nid
  213. WHERE n.type = :n.type
  214. AND n.status = :n.status
  215. AND h.status <> :h.status
  216. ORDER BY n.title
  217. ", array(
  218. ':n.type' => 'platform',
  219. ':n.status' => 1, //@todo: remove magic number?
  220. ':h.status' => HOSTING_PLATFORM_LOCKED,
  221. )
  222. );
  223. while ($platform = $result->fetch()) {
  224. $return[$platform->nid] = $platform->title;
  225. }
  226. return $return;
  227. }
  228. /**
  229. * Helper function to get platforms that have been locked.
  230. */
  231. function _hosting_get_locked_platforms() {
  232. $return = array();
  233. $result = db_query("SELECT n.nid, n.title
  234. FROM {node} n
  235. LEFT JOIN {hosting_platform} h
  236. ON n.nid = h.nid
  237. WHERE n.type = :type
  238. AND n.status = :nstatus
  239. AND h.status = :hstatus
  240. ORDER BY n.title
  241. ", array(
  242. ':type' => 'platform',
  243. ':nstatus' => NODE_PUBLISHED,
  244. ':hstatus' => HOSTING_PLATFORM_LOCKED,
  245. )
  246. );
  247. while ($platform = $result->fetch()) {
  248. $return[$platform->nid] = $platform->title;
  249. }
  250. return $return;
  251. }
  252. /**
  253. * Helper function to check if a platform is locked.
  254. */
  255. function _hosting_platform_is_locked($node) {
  256. if (in_array($node, array_keys(_hosting_get_locked_platforms()))) {
  257. return TRUE;
  258. }
  259. else {
  260. return FALSE;
  261. }
  262. }
  263. /**
  264. * Implements hook_form().
  265. */
  266. function hosting_platform_form(&$node) {
  267. $type = node_type_get_type($node);
  268. $form['title'] = array(
  269. '#type' => 'textfield',
  270. '#title' => t('Name'),
  271. '#required' => TRUE,
  272. '#description' => t('Choose a unique descriptive name for your platform. You very likely want this to be something like "Drupal 7.21".'),
  273. '#size' => 40,
  274. '#default_value' => $node->title,
  275. '#maxlength' => 255,
  276. );
  277. // Allow edition if the node is in creation, or if wasn't verified correctly
  278. // *and* we're not using a makefile. The reason while we don't allow editing
  279. // the path if the makefile was specified is that there's the possibility
  280. // that the platform path was actually created when the node was saved the
  281. // first time and we have cruft lying around to cleanup.
  282. if (!isset($node->nid) || (!$node->verified && !isset($node->makefile))) {
  283. $base_path = variable_get('hosting_platform_base_path', '/var/aegir/platforms/');
  284. $default_path = '';
  285. if (isset($node->publish_path)) {
  286. // Strip the $base_path, since we prepend it in a validation handler.
  287. // This enforces platform publishing under the defined base path, even if
  288. // an error allows the path to be edited again.
  289. if (substr($node->publish_path, 0, strlen($base_path)) == $base_path) {
  290. $default_path = substr($node->publish_path, strlen($base_path));
  291. }
  292. }
  293. $form['publish_path'] = array(
  294. '#type' => 'machine_name',
  295. '#machine_name' => array(
  296. 'exists' => 'hosting_platform_path_exists',
  297. 'source' => array('title'),
  298. 'label' => t('Publish path'),
  299. 'standalone' => TRUE,
  300. 'replace_pattern' => '[^a-z0-9_\.\-\/]+',
  301. 'field_prefix' => variable_get('hosting_platform_base_path', '/var/aegir/platforms/'),
  302. ),
  303. '#title' => t('Publish path'),
  304. '#weight' => -5,
  305. '#required' => TRUE,
  306. '#description' => t('The absolute path on the filesystem where the sites will be hosted. This needs to be created manually and initialized before your platform works properly. It also needs to be a unique path not already in use by a platform on any server.<br />For example, run the following shell commands:<pre>%commands</pre>Your publish path is the absolute path to the directory that gets created.<br />Alternatively, you can specify a makefile below, and the platform will be created automatically if the path specified here does not exist.<br />You are still required to enter the absolute path above, as it will be treated as the target directory by the makefile.', array('%commands' => "cd /var/aegir/platforms\ndrush dl drupal\n")),
  307. '#size' => 40,
  308. '#default_value' => $default_path,
  309. '#maxlength' => 255,
  310. '#field_prefix' => $base_path,
  311. );
  312. }
  313. else {
  314. // Display it.
  315. $form['info']['publish_path'] = array(
  316. '#type' => 'item',
  317. '#title' => t('Publish path'),
  318. '#markup' => $node->publish_path,
  319. );
  320. // Send it on form submission.
  321. $form['publish_path'] = array(
  322. '#type' => 'hidden',
  323. '#value' => $node->publish_path,
  324. );
  325. }
  326. $form['frommakefile'] = array(
  327. '#type' => 'fieldset',
  328. '#tree' => TRUE,
  329. '#title' => t('Deploy from makefile'),
  330. '#collapsible' => TRUE,
  331. '#description' => t('You may deploy this platform from a makefile.'),
  332. '#weight' => -1,
  333. );
  334. $form['frommakefile']['makefile'] = array(
  335. '#type' => 'textfield',
  336. '#title' => t('Makefile'),
  337. '#description' => t('The absolute path on the filesystem or public URL of a makefile that will be used to create the platform in the directory specified above. If the directory already exists, this file will be ignored.'),
  338. '#size' => 40,
  339. '#default_value' => isset($node->makefile) ? $node->makefile : NULL,
  340. '#maxlength' => 255,
  341. );
  342. $form['frommakefile']['make_working_copy'] = array(
  343. '#type' => 'radios',
  344. '#title' => t('Drush make option'),
  345. '#default_value' => isset($node->make_working_copy) ? $node->make_working_copy : 0,
  346. '#options' => array(
  347. 0 => t('Normal - Discards SCM files'),
  348. 1 => t('Working copy - preserves SCM files'),
  349. ),
  350. );
  351. $form['#after_build'][] = 'hosting_platform_form_platform_after_build';
  352. $servers = hosting_get_servers('http');
  353. if (count($servers) > 1) {
  354. $form['web_server'] = array(
  355. '#type' => 'radios',
  356. '#title' => t('Web server'),
  357. '#description' => t('The web server the sites will be hosted on.'),
  358. '#options' => $servers,
  359. '#default_value' => isset($node->web_server) ? $node->web_server : HOSTING_DEFAULT_WEB_SERVER,
  360. );
  361. }
  362. else {
  363. reset($servers);
  364. $form['web_server'] = array(
  365. '#type' => 'hidden',
  366. '#value' => key($servers),
  367. );
  368. }
  369. foreach (array('verified', 'platform_status') as $extra_attribute) {
  370. $form["$extra_attribute"] = array(
  371. '#type' => 'value',
  372. '#value' => isset($node->$extra_attribute) ? $node->$extra_attribute : NULL,
  373. );
  374. }
  375. $form['#submit'][] = 'hosting_platform_form_validate';
  376. return $form;
  377. }
  378. /**
  379. * After build callback for the hosting_platform_form.
  380. */
  381. function hosting_platform_form_platform_after_build($form) {
  382. drupal_add_js(drupal_get_path('module', 'hosting_platform') . '/hosting_platform.js');
  383. $form['frommakefile']['makefile']['#attributes']['class'][] = ' hosting-platform-working-copy-source';
  384. $form['frommakefile']['make_working_copy']['#attributes']['class'][] = ' hosting-platform-working-copy-target';
  385. return $form;
  386. }
  387. /**
  388. * Hide the delete button on platform nodes.
  389. */
  390. function hosting_platform_form_alter(&$form, &$form_state, $form_id) {
  391. switch ($form_id) {
  392. case 'platform_node_form':
  393. // Remove delete button from platform edit form,
  394. // unless the platform's already been deleted via the Delete task.
  395. $node = $form['#node'];
  396. if (isset($node->platform_status) && $node->platform_status !== HOSTING_PLATFORM_DELETED) {
  397. $form['actions']['delete']['#type'] = 'hidden';
  398. }
  399. break;
  400. case 'hosting_settings':
  401. $form['hosting_platform_base_path'] = array(
  402. '#type' => 'textfield',
  403. '#title' => t('Platform base path'),
  404. '#description' => t('The base path for your platforms, i.e. /var/aegir/platforms/'),
  405. '#default_value' => variable_get('hosting_platform_base_path', '/var/aegir/platforms/'),
  406. );
  407. break;
  408. }
  409. }
  410. /**
  411. * Implements hook_insert().
  412. */
  413. function hosting_platform_insert($node) {
  414. if (!isset($node->no_verify)) {
  415. hosting_add_task($node->nid, 'verify');
  416. }
  417. $id = db_insert('hosting_platform')
  418. ->fields(array(
  419. 'vid' => $node->vid,
  420. 'nid' => $node->nid,
  421. 'publish_path' => $node->publish_path,
  422. 'makefile' => isset($node->makefile) ? $node->makefile : (isset($node->frommakefile['makefile']) ? $node->frommakefile['makefile'] : ''),
  423. 'verified' => isset($node->verified) ? $node->verified : 0,
  424. 'web_server' => $node->web_server,
  425. 'status' => isset($node->platform_status) ? $node->platform_status : 0,
  426. 'make_working_copy' => isset($node->frommakefile['make_working_copy']) ? $node->frommakefile['make_working_copy'] : 0,
  427. ))
  428. ->execute();
  429. if (!isset($node->old_vid)) {
  430. hosting_context_register($node->nid, 'platform_' . preg_replace("/[!\W]/", "", $node->title));
  431. }
  432. }
  433. /**
  434. * Implements hook_update().
  435. *
  436. * As an existing node is being updated in the database, we need to do our own
  437. * database updates.
  438. */
  439. function hosting_platform_update($node) {
  440. // If this is a new node or we're adding a new revision.
  441. if (!empty($node->revision)) {
  442. hosting_platform_insert($node);
  443. }
  444. else {
  445. if ($node->platform_status == HOSTING_PLATFORM_DELETED) {
  446. $node->no_verify = TRUE;
  447. }
  448. db_update('hosting_platform')
  449. ->fields(array(
  450. 'publish_path' => $node->publish_path,
  451. 'makefile' => isset($node->makefile) ? $node->makefile : (isset($node->frommakefile['makefile']) ? $node->frommakefile['makefile'] : ''),
  452. 'web_server' => $node->web_server,
  453. 'verified' => $node->verified,
  454. 'status' => $node->platform_status,
  455. 'make_working_copy' => isset($node->frommakefile['make_working_copy']) ? $node->frommakefile['make_working_copy'] : $node->make_working_copy,
  456. ))
  457. ->condition('nid', $node->nid)
  458. ->execute();
  459. }
  460. if (!isset($node->no_verify)) {
  461. hosting_add_task($node->nid, 'verify');
  462. }
  463. }
  464. /**
  465. * Implements hook_nodeapi_TYPE_OP().
  466. */
  467. function hosting_nodeapi_platform_delete_revision(&$node) {
  468. db_delete('hosting_platform')
  469. ->condition('vid', $node->vid)
  470. ->execute();
  471. }
  472. /**
  473. * Implements hook_delete().
  474. */
  475. function hosting_platform_delete($node) {
  476. db_delete('hosting_platform')
  477. ->condition('nid', $node->nid)
  478. ->execute();
  479. db_delete('hosting_package_instance')
  480. ->condition('rid', $node->nid)
  481. ->execute();
  482. hosting_context_delete($node->nid);
  483. hosting_task_delete_related_tasks($node->nid);
  484. $result = db_query("SELECT distinct nid FROM {hosting_site} WHERE platform = :platform", array(':platform' => $node->nid));
  485. while ($nid = $result->fetch()) {
  486. node_delete($nid->nid);
  487. }
  488. }
  489. /**
  490. * Form validation for platforms.
  491. */
  492. function hosting_platform_form_validate(&$form, &$form_state) {
  493. // Prepend our platform base path, if this is a new platform.
  494. $node = $form['#node'];
  495. if (!isset($node->nid)) {
  496. $form_state['values']['publish_path'] = variable_get('hosting_platform_base_path', '/var/aegir/platforms/') . $form_state['values']['publish_path'];
  497. }
  498. }
  499. /**
  500. * Implements hook_validate().
  501. */
  502. function hosting_platform_validate($node, &$form) {
  503. if ($node->op != t('Delete')) {
  504. // Make sure the platform name is unique, to avoid context clashes.
  505. $result = db_query("SELECT n.title AS name
  506. FROM {hosting_platform} AS h
  507. INNER JOIN {node} AS n ON n.nid = h.nid
  508. WHERE n.title = !n.title
  509. AND n.nid <> !n.nid
  510. AND h.status >= !h.status",
  511. array(
  512. '!n.title' => $node->title,
  513. '!n.nid' => $node->nid,
  514. '!h.status' => HOSTING_PLATFORM_QUEUED,
  515. )
  516. )->fetch();
  517. if ($result) {
  518. form_set_error('title',
  519. t('Platform name %name is already defined. Platform names must be unique across all servers.',
  520. array('%name' => $result->name))
  521. );
  522. }
  523. // Make sure the path is unique. Remote servers can't have the same path to a platform that is in use by another server.
  524. $exists = hosting_platform_path_exists($node->publish_path);
  525. if ($exists) {
  526. form_set_error('publish_path',
  527. t('Path is already in use by platform %name. Platform paths must be unique across all servers.',
  528. array('%name' => $result->name))
  529. );
  530. }
  531. if (is_null($node->web_server)) {
  532. form_set_error('web_server', t('Platform needs to be associated with a webserver. Make sure you have a verified webserver on this Aegir install!'));
  533. }
  534. }
  535. }
  536. /**
  537. * Determine whether a given path has already been used with an existing
  538. * platform.
  539. */
  540. function hosting_platform_path_exists($path) {
  541. $result = db_query("SELECT n.title AS name
  542. FROM {hosting_platform} AS h
  543. INNER JOIN {node} AS n ON n.nid = h.nid
  544. WHERE publish_path = !publish_path
  545. AND h.status >= !h.status",
  546. array(
  547. '!publish_path' => hosting_path_normalize($path),
  548. '!h.status' => HOSTING_PLATFORM_QUEUED,
  549. )
  550. )->fetch();
  551. return $result;
  552. }
  553. /**
  554. * Implements hook_load().
  555. */
  556. function hosting_platform_load($nodes) {
  557. foreach ($nodes as $nid => &$node) {
  558. $additions = db_query('SELECT publish_path, makefile, verified, web_server, status AS platform_status, make_working_copy FROM {hosting_platform} WHERE vid = :vid', array(':vid' => $node->vid))->fetch();
  559. // Avoid PHP 5.4 warning when platform doesn't exist yet.
  560. // See: https://drupal.org/node/1940378
  561. $additions = $additions ? $additions : new stdClass();
  562. $iid = db_query("SELECT iid
  563. FROM {hosting_package_instance} i
  564. LEFT JOIN {hosting_package} p
  565. ON p.nid=i.package_id
  566. WHERE p.package_type = :package_type
  567. AND i.rid = :rid",
  568. array(
  569. ':package_type' => 'platform',
  570. ':rid' => $node->nid,
  571. )
  572. )->fetchField();
  573. if (empty($node->frommakefile)) {
  574. $node->frommakefile = array('makefile' => '', 'make_working_copy' => 0);
  575. }
  576. if (!empty($additions->makefile)) {
  577. $node->frommakefile['makefile'] = $additions->makefile;
  578. }
  579. if (!empty($additions->make_working_copy)) {
  580. $node->frommakefile['make_working_copy'] = $additions->make_working_copy;
  581. }
  582. $additions->release = hosting_package_instance_load($iid);
  583. $additions->profiles = hosting_get_profiles($node->nid, 'short_name');
  584. if (hosting_feature('client')) {
  585. $result = db_query("SELECT cid FROM {hosting_platform_client_access} WHERE pid = :pid", array(':pid' => $node->nid));
  586. foreach ($result as $record) {
  587. $additions->clients[$record->cid] = $record->cid;
  588. }
  589. }
  590. foreach ($additions as $property => &$value) {
  591. $node->$property = $value;
  592. }
  593. }
  594. }
  595. /**
  596. * Menu wildcard loader callback.
  597. *
  598. * Loads a hosting_platform node.
  599. * @see hosting_task_menu()
  600. *
  601. * @param int $arg
  602. * Node's numeric nid
  603. *
  604. * @return bool|object
  605. * A platforn node object or FALSE.
  606. */
  607. function hosting_platform_wildcard_load($arg) {
  608. if (!is_numeric($arg)) {
  609. return FALSE;
  610. }
  611. if ($node = node_load($arg)) {
  612. if ($node->type == 'platform') {
  613. return $node;
  614. }
  615. }
  616. return FALSE;
  617. }
  618. /**
  619. * Implements hook_view().
  620. */
  621. function hosting_platform_view($node, $teaser = FALSE, $page = FALSE) {
  622. $node->content['info'] = array(
  623. '#prefix' => '<div id="hosting-platform-info" class="hosting-info-list">',
  624. '#suffix' => '</div>',
  625. );
  626. $node->content['info']['verified'] = array(
  627. '#type' => 'item',
  628. '#title' => t('Verified'),
  629. '#markup' => hosting_format_interval($node->verified),
  630. '#weight' => -10,
  631. );
  632. $node->content['info']['publish_path'] = array(
  633. '#type' => 'item',
  634. '#title' => t('Publish path'),
  635. '#markup' => filter_xss($node->publish_path),
  636. '#weight' => -8,
  637. );
  638. $node->content['info']['web_server'] = array(
  639. '#type' => 'item',
  640. '#title' => t('Web server'),
  641. '#markup' => _hosting_node_link($node->web_server),
  642. '#weight' => -7,
  643. );
  644. $node->content['info']['status'] = array(
  645. '#type' => 'item',
  646. '#title' => t('Status'),
  647. '#markup' => _hosting_platform_status($node->platform_status),
  648. );
  649. if ($node->makefile) {
  650. $node->content['info']['makefile'] = array(
  651. '#type' => 'item',
  652. '#title' => t('Drush makefile'),
  653. '#markup' => (preg_match('/^http|^ftp/', $node->makefile)) ? l(t('makefile'), $node->makefile) : filter_xss($node->makefile),
  654. );
  655. }
  656. if ($node->release) {
  657. $release = sprintf("%s %s", $node->release->title, $node->release->version);
  658. $node->content['info']['release'] = array(
  659. '#type' => 'item',
  660. '#title' => t('Release'),
  661. '#markup' => _hosting_node_link($node->release->nid, $release),
  662. '#weight' => -6,
  663. );
  664. }
  665. // Task list.
  666. if ($page && $node->nid) {
  667. $node->content['tasks_view'] = array(
  668. '#type' => 'item',
  669. '#markup' => hosting_task_table($node),
  670. '#prefix' => '<div id="hosting-task-list">',
  671. '#suffix' => '</div>',
  672. '#weight' => 9,
  673. );
  674. $settings['hostingTaskRefresh'] = array(
  675. 'nid' => $node->nid,
  676. 'changed' => $node->changed,
  677. );
  678. drupal_add_js($settings, array('type' => 'setting', 'scope' => JS_DEFAULT));
  679. drupal_add_js(drupal_get_path('module', 'hosting_task') . '/hosting_task.js');
  680. }
  681. return $node;
  682. }
  683. /**
  684. * Implements hook_hosting_site_site_list_filters().
  685. */
  686. function hosting_platform_hosting_site_site_list_filters() {
  687. return array('platform');
  688. }
  689. /**
  690. * Helper function to map status codes to labels and classes.
  691. */
  692. function _hosting_platform_status_codes() {
  693. $codes = array(
  694. HOSTING_PLATFORM_QUEUED => array(
  695. 'label' => 'Queued',
  696. 'class' => 'hosting-queue',
  697. ),
  698. HOSTING_PLATFORM_ENABLED => array(
  699. 'label' => 'Enabled',
  700. 'class' => 'hosting-success',
  701. ),
  702. HOSTING_PLATFORM_DELETED => array(
  703. 'label' => 'Deleted',
  704. 'class' => 'hosting-error',
  705. ),
  706. HOSTING_PLATFORM_LOCKED => array(
  707. 'label' => 'Locked',
  708. 'class' => 'hosting-disable',
  709. ),
  710. );
  711. return $codes;
  712. }
  713. /**
  714. * Return the appropriate status label.
  715. */
  716. function _hosting_platform_status($status) {
  717. static $labels;
  718. $labels = _hosting_platform_status_codes();
  719. return is_object($status) ? $labels[$status->platform_status]['label'] : $labels[$status]['label'];
  720. }
  721. /**
  722. * Implements hook_hosting_summary().
  723. */
  724. function hosting_platform_hosting_summary() {
  725. $summary = array();
  726. if (user_access('view locked platforms')) {
  727. $platforms = _hosting_get_platforms();
  728. $summary['platforms'] = theme('item_list', array('items' => array_map('_hosting_node_link', array_keys($platforms)), 'title' => t('Platforms')));
  729. }
  730. elseif (user_access('view platform')) {
  731. $platforms = _hosting_get_enabled_platforms();
  732. $summary['platforms'] = theme('item_list', array('items' => array_map('_hosting_node_link', array_keys($platforms)), 'title' => t('Platforms')));
  733. }
  734. return $summary;
  735. }
  736. /**
  737. * Implements hook_views_api().
  738. */
  739. function hosting_platform_views_api() {
  740. return array(
  741. 'api' => 3,
  742. 'path' => drupal_get_path('module', 'hosting_platform') . '/includes/views',
  743. );
  744. }
  745. /**
  746. * Define the classes that correspond to the platform status.
  747. */
  748. function _hosting_platform_list_class($status) {
  749. static $labels;
  750. $labels = _hosting_platform_status_codes();
  751. return is_object($status) ? $labels[$status->platform_status]['class'] : $labels[$status]['class'];
  752. }