profile2_page.module 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <?php
  2. /**
  3. * @file
  4. * Adds separate pages for viewing and editing profiles.
  5. */
  6. /**
  7. * Implements hook_menu().
  8. */
  9. function profile2_page_menu() {
  10. $items = array();
  11. // Bugfix for uninstalling the module, see http://drupal.org/node/1008346.
  12. if (!module_exists('profile2')) {
  13. return;
  14. }
  15. foreach (profile2_get_types() as $type_name => $type) {
  16. if (!empty($type->data['use_page'])) {
  17. $path = profile2_page_get_base_path($type);
  18. $count = count(explode('/', $path));
  19. $items[$path] = array(
  20. 'title callback' => 'profile2_page_title',
  21. 'title arguments' => array($type_name),
  22. 'page callback' => 'profile2_page_own',
  23. 'page arguments' => array($path),
  24. 'access callback' => 'user_access',
  25. 'access arguments' => array("edit own $type_name profile"),
  26. 'file' => 'profile2_page.inc',
  27. 'menu_name' => 'user-menu',
  28. );
  29. $items[$path . '/%profile2_by_uid'] = array(
  30. 'title callback' => 'profile2_page_title',
  31. 'title arguments' => array($type_name, $count),
  32. 'page callback' => 'profile2_page_view',
  33. 'page arguments' => array($count),
  34. 'load arguments' => array($type_name),
  35. 'access callback' => 'profile2_access',
  36. 'access arguments' => array('view', $count),
  37. 'file' => 'profile2_page.inc',
  38. // Copied over the following hack from user_menu() to avoid $path
  39. // appearing in the breadcrumb:
  40. //
  41. // By assigning a different menu name, this item (and all registered
  42. // child paths) are no longer considered as children of 'user'. When
  43. // accessing the user account pages, the preferred menu link that is
  44. // used to build the active trail (breadcrumb) will be found in this
  45. // menu (unless there is more specific link), so the link to 'user' will
  46. // not be in the breadcrumb.
  47. 'menu_name' => 'navigation',
  48. );
  49. $items[$path . '/%profile2_by_uid/view'] = array(
  50. 'title' => 'View',
  51. 'type' => MENU_DEFAULT_LOCAL_TASK,
  52. 'load arguments' => array($type_name),
  53. 'weight' => -10,
  54. );
  55. $items[$path . '/%profile2_by_uid/edit'] = array(
  56. 'page callback' => 'entity_ui_get_form',
  57. 'page arguments' => array('profile2', $count),
  58. 'load arguments' => array($type_name),
  59. 'access callback' => 'profile2_access',
  60. 'access arguments' => array('edit', $count),
  61. 'title' => 'Edit',
  62. 'type' => MENU_LOCAL_TASK,
  63. 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
  64. 'file' => 'profile2_page.inc',
  65. );
  66. $items[$path . '/%profile2_by_uid/delete'] = array(
  67. 'page callback' => 'drupal_get_form',
  68. 'page arguments' => array('profile2_page_delete_confirm_form', $count),
  69. 'load arguments' => array($type_name),
  70. 'access callback' => 'profile2_access',
  71. 'access arguments' => array('delete', $count),
  72. 'title' => 'Delete',
  73. 'type' => MENU_LOCAL_TASK,
  74. 'context' => MENU_CONTEXT_INLINE,
  75. 'file' => 'profile2_page.inc',
  76. );
  77. // Devel integration.
  78. if (module_exists('devel')) {
  79. $devel_path = drupal_get_path('module', 'devel');
  80. $items[$path . '/%profile2_by_uid/devel'] = array(
  81. 'title' => 'Devel',
  82. 'page callback' => 'devel_load_object',
  83. 'file' => 'devel.pages.inc',
  84. 'file path' => $devel_path,
  85. 'page arguments' => array('profile2', $count),
  86. 'access arguments' => array('access devel information'),
  87. 'type' => MENU_LOCAL_TASK,
  88. 'weight' => 100,
  89. );
  90. $items[$path . '/%profile2_by_uid/devel/load'] = array(
  91. 'title' => 'Load',
  92. 'type' => MENU_DEFAULT_LOCAL_TASK,
  93. );
  94. $items[$path . '/%profile2_by_uid/devel/render'] = array(
  95. 'title' => 'Render',
  96. 'page callback' => 'devel_render_object',
  97. 'page arguments' => array('profile2', $count),
  98. 'access arguments' => array('access devel information'),
  99. 'file' => 'devel.pages.inc',
  100. 'file path' => $devel_path,
  101. 'type' => MENU_LOCAL_TASK,
  102. 'weight' => 100,
  103. );
  104. }
  105. }
  106. }
  107. return $items;
  108. }
  109. /**
  110. * Menu load callback.
  111. *
  112. * Returns the profile object for the given user. If there is none yet, a new
  113. * object is created.
  114. */
  115. function profile2_by_uid_load($uid, $type_name) {
  116. if ($uid && is_numeric($uid) && ($account = user_load($uid))) {
  117. $profile = profile2_load_by_user($account, $type_name);
  118. if (!$profile) {
  119. $profile = profile2_create(array('type' => $type_name));
  120. $profile->setUser($account);
  121. $profile->is_new = TRUE;
  122. }
  123. return $profile;
  124. }
  125. return FALSE;
  126. }
  127. /**
  128. * Returns the base path to use as profile page.
  129. */
  130. function profile2_page_get_base_path($profile_type) {
  131. // Allow for an easy customization of the page's base path.
  132. if (!empty($profile_type->data['page_path'])) {
  133. return $profile_type->data['page_path'];
  134. }
  135. return 'profile-' . $profile_type->type;
  136. }
  137. /**
  138. * Implements hook_forms().
  139. */
  140. function profile2_page_forms($form_id, $args) {
  141. // For efficiency, only act if the third argument is 'profile2'.
  142. if (isset($args[2]) && is_string($args[2]) && $args[2] == 'profile2') {
  143. $info = entity_get_info('profile2');
  144. // Translate bundle form ids to the base form id 'profile2_form'.
  145. foreach ($info['bundles'] as $bundle => $bundle_info) {
  146. $forms['profile2_edit_' . $bundle . '_form']['callback'] = 'profile2_form';
  147. $forms['profile2_edit_' . $bundle . '_form']['wrapper callback'] = 'entity_ui_form_defaults';
  148. }
  149. return $forms;
  150. }
  151. }
  152. /**
  153. * Implements hook_profile2_type_load().
  154. */
  155. function profile2_page_profile2_type_load($types) {
  156. foreach ($types as $type) {
  157. if (!empty($type->data['use_page'])) {
  158. // Disable user categories and the user account view.
  159. $type->userCategory = FALSE;
  160. $type->userView = FALSE;
  161. }
  162. }
  163. }
  164. /**
  165. * Implements hook_entity_info_alter().
  166. */
  167. function profile2_page_entity_info_alter(&$entity_info) {
  168. // Add new view modes for the page.
  169. $entity_info['profile2']['view modes']['page'] = array(
  170. 'label' => t('Profile page'),
  171. 'custom settings' => FALSE,
  172. );
  173. $entity_info['profile2']['view modes']['teaser'] = array(
  174. 'label' => t('Teaser'),
  175. 'custom settings' => FALSE,
  176. );
  177. $entity_info['profile2']['uri callback'] = 'profile2_page_uri_callback';
  178. $entity_info['profile2']['form callback'] = 'profile2_page_form_callback';
  179. }
  180. /**
  181. * URI callback pointing to the profile page.
  182. *
  183. * @see profile2_pages_entity_info_alter()
  184. */
  185. function profile2_page_uri_callback($profile) {
  186. $type = $profile->type();
  187. if (!empty($type->data['use_page'])) {
  188. return array('path' => profile2_page_get_base_path($type) . '/' . $profile->uid);
  189. }
  190. // Fall back to the default callback.
  191. return $profile->defaultUri();
  192. }
  193. /**
  194. * Form callback for entity_form().
  195. */
  196. function profile2_page_form_callback($profile) {
  197. // Pre-populate the form-state with the right form include.
  198. $form_state = form_state_defaults();
  199. form_load_include($form_state, 'inc', 'profile2_page');
  200. return entity_ui_get_form('profile2', $profile, 'edit', $form_state);
  201. }
  202. /**
  203. * Menu title callback.
  204. */
  205. function profile2_page_title($type_name, $profile2 = NULL) {
  206. $type = profile2_get_types($type_name);
  207. // If no profile is given, we are at the general path pointing to the own
  208. // profile.
  209. if (!isset($profile2)) {
  210. return t('My @profile-label', array('@profile-label' => drupal_strtolower($type->getTranslation('label'))));
  211. }
  212. return drupal_ucfirst($profile2->label());
  213. }
  214. /**
  215. * Implements hook_form_FORM_ID_alter() for the profile2 type form..
  216. */
  217. function profile2_page_form_profile2_type_form_alter(&$form, &$form_state) {
  218. $type = $form_state['profile2_type'];
  219. $form['data']['use_page'] = array(
  220. '#type' => 'checkbox',
  221. '#title' => t('Provide a separate page for editing profiles.'),
  222. '#description' => t('If enabled, a separate menu item for editing the profile is generated and the profile is hidden from the user account page.'),
  223. '#default_value' => !empty($type->is_new) || !empty($type->data['use_page']),
  224. );
  225. $form['data']['#tree'] = TRUE;
  226. }
  227. /**
  228. * Implements hook_profile2_type_insert().
  229. */
  230. function profile2_page_profile2_type_insert(ProfileType $type) {
  231. // Do not directly issue menu rebuilds here to avoid potentially multiple
  232. // rebuilds. Instead, let menu_get_item() issue the rebuild on the next page.
  233. if (!empty($type->data['use_page'])) {
  234. variable_set('menu_rebuild_needed', TRUE);
  235. }
  236. }
  237. /**
  238. * Implements hook_profile2_type_update().
  239. */
  240. function profile2_page_profile2_type_update(ProfileType $type) {
  241. // Rebuild the menu if use_page or the type name has been changed.
  242. // @see profile2_page_profile2_type_insert()
  243. if (empty($type->data['use_page']) != empty($type->original->data['use_page']) || ($type->data['use_page'] && $type->type != $type->original->type)) {
  244. variable_set('menu_rebuild_needed', TRUE);
  245. }
  246. }
  247. /**
  248. * Implements hook_profile2_type_delete()
  249. */
  250. function profile2_page_profile2_type_delete($type) {
  251. // Do not directly issue menu rebuilds here to avoid potentially multiple
  252. // rebuilds. Instead, let menu_get_item() issue the rebuild on the next page.
  253. if (!empty($type->data['use_page'])) {
  254. variable_set('menu_rebuild_needed', TRUE);
  255. }
  256. }