rolereference.module 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. <?php
  2. /**
  3. * Implements hook_field_info().
  4. */
  5. function rolereference_field_info() {
  6. return array(
  7. 'rolereference' => array(
  8. 'label' => t('Role reference'),
  9. 'description' => t('This field stores the ID of a related role as an integer value.'),
  10. 'settings' => array('referenceable_roles' => array()),
  11. 'default_widget' => 'options_select',
  12. 'default_formatter' => 'rolereference_default',
  13. 'property_type' => 'integer',
  14. ),
  15. );
  16. }
  17. /**
  18. * Implements hook_field_schema().
  19. */
  20. function rolereference_field_schema($field) {
  21. $columns = array(
  22. 'rid' => array(
  23. 'type' => 'int',
  24. 'unsigned' => TRUE,
  25. 'not null' => FALSE,
  26. ),
  27. );
  28. return array(
  29. 'columns' => $columns,
  30. 'indexes' => array('rid' => array('rid')),
  31. 'foreign keys' => array(
  32. 'rid' => array(
  33. 'table' => 'role',
  34. 'columns' => array('rid' => 'rid'),
  35. ),
  36. ),
  37. );
  38. }
  39. /**
  40. * Implements hook_field_settings_form().
  41. */
  42. function rolereference_field_settings_form($field, $instance, $has_data) {
  43. $settings = $field['settings'];
  44. $form = array();
  45. $role_options = array_map('check_plain', user_roles());
  46. $form['referenceable_roles'] = array(
  47. '#type' => 'checkboxes',
  48. '#title' => t('Roles that can be referenced'),
  49. '#description' => t('Select roles that may be referenced by this field. All roles will be available if none are checked.'),
  50. '#multiple' => TRUE,
  51. '#default_value' => is_array($settings['referenceable_roles']) ? $settings['referenceable_roles'] : array(),
  52. '#options' => $role_options,
  53. '#disabled' => $has_data,
  54. );
  55. return $form;
  56. }
  57. /**
  58. * Implements hook_field_validate().
  59. *
  60. * Possible error codes:
  61. * - 'invalid_rid': nid is not valid for the field
  62. * (not a valid role id, or the role is not referenceable).
  63. */
  64. function rolereference_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
  65. // Extract nids to check.
  66. $ids = array();
  67. // First check non-numeric rid's to avoid losing time with them.
  68. foreach ($items as $delta => $item) {
  69. if (is_array($item) && !empty($item['rid'])) {
  70. if (is_numeric($item['rid'])) {
  71. $ids[] = $item['rid'];
  72. }
  73. else {
  74. $errors[$field['field_name']][$langcode][$delta][] = array(
  75. 'error' => 'invalid_rid',
  76. 'message' => t("%name: invalid input.",
  77. array('%name' => $instance['label'])),
  78. );
  79. }
  80. }
  81. }
  82. // Prevent performance hog if there are no ids to check.
  83. if ($ids) {
  84. $referenceable_roles = rolereference_potential_references($field['settings']['referenceable_roles'], $field['field_name']);
  85. foreach ($items as $delta => $item) {
  86. if (is_array($item)) {
  87. if (!empty($item['rid']) && !isset($referenceable_roles[$item['rid']])) {
  88. $errors[$field['field_name']][$langcode][$delta][] = array(
  89. 'error' => 'invalid_rid',
  90. 'message' => t("%name: this role can't be referenced.",
  91. array('%name' => $instance['label'])),
  92. );
  93. }
  94. }
  95. }
  96. }
  97. }
  98. /**
  99. * Implements hook_field_prepare_view().
  100. */
  101. function rolereference_field_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items) {
  102. $referenceable_roles = rolereference_potential_references($field['settings']['referenceable_roles'], $field['field_name']);
  103. // Extract nids to check.
  104. $ids = array();
  105. foreach ($items as $id => $entity_items) {
  106. foreach ($entity_items as $delta => $item) {
  107. if (is_array($item)) {
  108. // Default to 'not accessible'.
  109. $items[$id][$delta]['access'] = FALSE;
  110. if (!empty($item['rid']) && is_numeric($item['rid'])) {
  111. $ids[$item['rid']] = $item['rid'];
  112. }
  113. }
  114. }
  115. }
  116. if ($ids) {
  117. foreach ($items as $id => $entity_items) {
  118. foreach ($entity_items as $delta => $item) {
  119. if (is_array($item) && !empty($item['rid']) && isset($referenceable_roles[$item['rid']])) {
  120. $items[$id][$delta]['role'] = $referenceable_roles[$item['rid']];
  121. $items[$id][$delta]['access'] = TRUE;
  122. }
  123. }
  124. }
  125. }
  126. }
  127. /**
  128. * Implements hook_field_is_empty().
  129. */
  130. function rolereference_field_is_empty($item, $field) {
  131. if (empty($item['rid']) && (string) $item['rid'] !== '0') {
  132. return TRUE;
  133. }
  134. return FALSE;
  135. }
  136. /**
  137. * Implements hook_field_formatter_info().
  138. */
  139. function rolereference_field_formatter_info() {
  140. $ret = array(
  141. 'rolereference_default' => array(
  142. 'label' => t('Title'),
  143. 'description' => t('Display the title of the referenced role.'),
  144. 'field types' => array('rolereference'),
  145. ),
  146. );
  147. return $ret;
  148. }
  149. /**
  150. * Implements hook_field_formatter_view().
  151. */
  152. function rolereference_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  153. $element = array();
  154. switch ($display['type']) {
  155. case 'rolereference_default':
  156. foreach ($items as $delta => $item) {
  157. $element[$delta] = array('#markup' => check_plain($item['role']));
  158. }
  159. break;
  160. }
  161. return $element;
  162. }
  163. /**
  164. * Implements hook_field_widget_info_alter().
  165. */
  166. function rolereference_field_widget_info_alter(&$info) {
  167. $info['options_select']['field types'][] = 'rolereference';
  168. $info['options_buttons']['field types'][] = 'rolereference';
  169. }
  170. /**
  171. * Implements hook_options_list().
  172. */
  173. function rolereference_options_list($field) {
  174. return rolereference_potential_references($field['settings']['referenceable_roles'], $field['field_name']);
  175. }
  176. /**
  177. * Implements hook_views_api().
  178. */
  179. function rolereference_views_api() {
  180. return array(
  181. 'api' => '3.0',
  182. 'path' => drupal_get_path('module', 'rolereference') . '/includes',
  183. );
  184. }
  185. /**
  186. * Implements hook_field_views_data().
  187. *
  188. * In addition to the default field information we add the relationship for
  189. * views to connect back to the role table.
  190. */
  191. function rolereference_field_views_data($field) {
  192. $data = field_views_field_default_views_data($field);
  193. $storage = $field['storage']['details']['sql'];
  194. foreach ($storage as $age => $table_data) {
  195. $table = key($table_data);
  196. $columns = current($table_data);
  197. $id_column = $columns['rid'];
  198. if (isset($data[$table])) {
  199. $data[$table][$id_column]['relationship'] = array(
  200. 'base' => 'role',
  201. 'field' => $columns['rid'],
  202. 'base field' => 'rid',
  203. 'label' => $field['field_name'],
  204. );
  205. }
  206. }
  207. return $data;
  208. }
  209. /**
  210. * Return a rid->name array of referenceable roles, based on the field settings.
  211. *
  212. * @param {array} $referenceable_roles
  213. */
  214. function rolereference_potential_references($referenceable_roles, $field_name) {
  215. $roles = &drupal_static('rolereference_' . $field_name, array());
  216. $user_roles = user_roles();
  217. if (empty($roles)) {
  218. foreach ($user_roles as $rid => $role) {
  219. if (!empty($referenceable_roles[$rid])) {
  220. $roles[$rid] = $role;
  221. }
  222. }
  223. if (empty($roles)) {
  224. $roles = $user_roles;
  225. }
  226. }
  227. return $roles;
  228. }
  229. /**
  230. * Implements hook_content_migrate_field_alter().
  231. */
  232. function rolereference_content_migrate_field_alter(&$field_value, $instance_value) {
  233. switch ($instance_value['widget']['module']) {
  234. case 'rolereference':
  235. $field_value['settings']['referenceable_roles'] = $field_value['settings']['referenceable_types'];
  236. unset($field_value['settings']['referenceable_types']);
  237. break;
  238. }
  239. }
  240. /**
  241. * Implements hook_field_extract_info().
  242. *
  243. * This provides integration for the field_extract module,
  244. * making it easy to get the value of a rolereference field.
  245. *
  246. * Example: field_extract_value('node', $node, 'field_subscriber_role');
  247. *
  248. * @return $extractors
  249. * array: field_extract info for rolereference module.
  250. */
  251. function rolereference_field_extract_info() {
  252. $extractors = array(
  253. 'rolereference' => array(
  254. 'options' => array(
  255. 'key' => 'rid',
  256. ),
  257. ),
  258. );
  259. return $extractors;
  260. }
  261. /**
  262. * Implements feeds_processor_targets_alter().
  263. */
  264. function rolereference_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
  265. // Set up feeds mapper for rolereference fields.
  266. foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
  267. $info = field_info_field($name);
  268. if ($info['type'] == 'rolereference') {
  269. $targets[$name] = array(
  270. 'name' => check_plain($instance['label']),
  271. 'description' => t('Role reference field.'),
  272. 'callback' => 'rolereference_set_target',
  273. );
  274. }
  275. }
  276. }
  277. /**
  278. * Feeds callback to set mapping target.
  279. */
  280. function rolereference_set_target($source, $entity, $target, array $values, $mapping) {
  281. // Process rolereference field data.
  282. $info = field_info_field($target);
  283. if ($info['type'] == 'rolereference') {
  284. foreach ($values as $rid) {
  285. if (!empty($rid)) {
  286. $entity->{$target}[$entity->language][] = array('rid' => $rid);
  287. }
  288. }
  289. }
  290. }