field_permission_example.module 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. <?php
  2. /**
  3. * @file
  4. * An example field using the Field Types API.
  5. */
  6. /**
  7. * @defgroup field_permission_example Example: Field Permissions
  8. * @ingroup examples
  9. * @{
  10. * Example using permissions on a Field API field.
  11. *
  12. * This example is a relatively simple text field you can attach to
  13. * any fieldable entity.
  14. *
  15. * In this module we demonstrate how to limit access to a field.
  16. * Drupal's Field API gives you two operations to permit or restrict:
  17. * view and edit. So you can then decide who gets to see fields,
  18. * who can edit them, and who can manage them.
  19. *
  20. * Our field is called field_permission_example_fieldnote. It has a
  21. * simple default widget of a text area, and a default formatter
  22. * that applies a CSS style to make it look like a sticky note.
  23. *
  24. * In addition to demonstrating how to set up permissions-based
  25. * access to a field, this module also demonstrates the absolute
  26. * minimum required to implement a field, since it doesn't have
  27. * any field settings. The tests also have a generalized
  28. * field testing class, called FieldTestGeneric, which can be easily
  29. * subclassed and reused for other fields.
  30. *
  31. * If you wish to use this code as skeleton code for a field without
  32. * permissions, you can simply remove field_permission_exampe_permission()
  33. * and field_permission_field_access(). Also field_permission_example_menu()
  34. * and _field_permission_example_page() are vestigial to the Examples
  35. * project.
  36. *
  37. * How does it work?
  38. *
  39. * You can install this module and go to path /examples/field_permission_example
  40. * for an introduction on how to use this field. Or see the same content at
  41. * _field_permission_example_page().
  42. *
  43. * OK, how does the code work?
  44. *
  45. * As with any permission system, we implement hook_permission() in
  46. * order to define a few permissions. In our case, users will want
  47. * to either view or edit fieldnote fields. And, similar to the way
  48. * node permissions work, we'll also include a context of either
  49. * their own content or any content. So that gives us 4 permissions
  50. * which administrators can assign to various roles. See
  51. * field_permission_example_permission() for the list.
  52. *
  53. * With our permissions defined in hook_permission(), we can now
  54. * handle requests for access. Those come in through
  55. * hook_field_access(), which we've implemented as
  56. * field_permission_example_field_access(). This function determines
  57. * whether the user has the ability to view or edit the field
  58. * in question by calling user_access(). We also give special edit
  59. * access to users with the 'bypass node access' and
  60. * 'administer content types' permissions, defined by the node module.
  61. *
  62. * One tricky part is that our field won't always be attached to
  63. * nodes. It could be attached to any type of entity. This means
  64. * that there's no general way to figure out if the user 'owns'
  65. * the entity or not. Since this is a simple example, we'll just
  66. * check for 'any' access to unknown entity types. We'll also
  67. * limit our known entity types to node and user, since those
  68. * are easy to demonstrate.
  69. *
  70. * In a real application, we'd have use-case specific permissions
  71. * which might be more complex than these. Or perhaps simpler.
  72. *
  73. * You can see a more complex field implementation in
  74. * field_example.module.
  75. *
  76. * @see field_example
  77. * @see field_example.module
  78. * @see field_types
  79. * @see field
  80. */
  81. /**
  82. * Implements hook_permission().
  83. *
  84. * We want to let site administrators figure out who should
  85. * be able to view, edit, and administer our field.
  86. *
  87. * Field permission operations can only be view or edit, in the
  88. * context of one's own content or that of others. Contrast
  89. * with content types where we also have to worry about who can
  90. * create or delete content.
  91. */
  92. function field_permission_example_permission() {
  93. // Note: This would be very easy to generate programmatically,
  94. // but it's all typed out here for clarity.
  95. // The key text is the machine name of the permission.
  96. $perms['view own fieldnote'] = array('title' => t('View own fieldnote'));
  97. $perms['edit own fieldnote'] = array('title' => t('Edit own fieldnote'));
  98. $perms['view any fieldnote'] = array('title' => t('View any fieldnote'));
  99. $perms['edit any fieldnote'] = array('title' => t('Edit any fieldnote'));
  100. return $perms;
  101. }
  102. /**
  103. * Implements hook_field_access().
  104. *
  105. * We want to make sure that fields aren't being seen or edited
  106. * by those who shouldn't.
  107. *
  108. * We have to build a permission string similar to those in
  109. * hook_permission() in order to ask Drupal whether the user
  110. * has that permission. Permission strings will end up being
  111. * like 'view any fieldnote' or 'edit own fieldnote'.
  112. *
  113. * The tricky thing here is that a field can be attached to any type
  114. * of entity, so it's not always trivial to figure out whether
  115. * $account 'owns' the entity. We'll support access restrictions for
  116. * user and node entity types, and be permissive with others,
  117. * since that's easy to demonstrate.
  118. *
  119. * @see field_permission_example_permissions()
  120. */
  121. function field_permission_example_field_access($op, $field, $entity_type, $entity, $account) {
  122. // This hook will be invoked for every field type, so we have to
  123. // check that it's the one we're interested in.
  124. if ($field['type'] == 'field_permission_example_fieldnote') {
  125. // First we'll check if the user has the 'superuser'
  126. // permissions that node provides. This way administrators
  127. // will be able to administer the content types.
  128. if (user_access('bypass node access', $account)) {
  129. drupal_set_message(t('User can bypass node access.'));
  130. return TRUE;
  131. }
  132. if (user_access('administer content types', $account)) {
  133. drupal_set_message(t('User can administer content types.'));
  134. return TRUE;
  135. }
  136. // Now check for our own permissions.
  137. // $context will end up being either 'any' or 'own.'
  138. $context = 'any';
  139. switch ($entity_type) {
  140. case 'user':
  141. case 'node':
  142. // While administering the field itself, $entity will be
  143. // NULL, so we have to check it.
  144. if ($entity) {
  145. if ($entity->uid == $account->uid) {
  146. $context = 'own';
  147. }
  148. }
  149. }
  150. // Assemble a permission string, such as
  151. // 'view any fieldnote'
  152. $permission = $op . ' ' . $context . ' fieldnote';
  153. // Finally, ask Drupal if this account has that permission.
  154. $access = user_access($permission, $account);
  155. $status = 'FALSE';
  156. if ($access) {
  157. $status = 'TRUE';
  158. }
  159. drupal_set_message($permission . ': ' . $status);
  160. return $access;
  161. }
  162. // We have no opinion on field types other than our own.
  163. return TRUE;
  164. }
  165. /**
  166. * Implements hook_field_info().
  167. *
  168. * Provides the description of the field.
  169. */
  170. function field_permission_example_field_info() {
  171. return array(
  172. // We name our field as the associative name of the array.
  173. 'field_permission_example_fieldnote' => array(
  174. 'label' => t('Fieldnote'),
  175. 'description' => t('Place a note-taking field on entities, with granular permissions.'),
  176. 'default_widget' => 'field_permission_example_widget',
  177. 'default_formatter' => 'field_permission_example_formatter',
  178. ),
  179. );
  180. }
  181. /**
  182. * Implements hook_field_is_empty().
  183. *
  184. * hook_field_is_empty() is where Drupal asks us if this field is empty.
  185. * Return TRUE if it does not contain data, FALSE if it does. This lets
  186. * the form API flag an error when required fields are empty.
  187. */
  188. function field_permission_example_field_is_empty($item, $field) {
  189. return empty($item['notes']);
  190. }
  191. /**
  192. * Implements hook_field_formatter_info().
  193. *
  194. * We need to tell Drupal about our excellent field formatter.
  195. *
  196. * It's some text in a div, styled to look like a sticky note.
  197. *
  198. * @see field_permission_example_field_formatter_view()
  199. */
  200. function field_permission_example_field_formatter_info() {
  201. return array(
  202. // This formatter simply displays the text in a text field.
  203. 'field_permission_example_formatter' => array(
  204. 'label' => t('Simple text-based formatter'),
  205. 'field types' => array('field_permission_example_fieldnote'),
  206. ),
  207. );
  208. }
  209. /**
  210. * Implements hook_field_formatter_view().
  211. *
  212. * Here we output the field for general consumption.
  213. *
  214. * The field will have a sticky note appearance, thanks to some
  215. * simple CSS.
  216. *
  217. * Note that all of the permissions and access logic happens
  218. * in hook_field_access(), and none of it is here.
  219. */
  220. function field_permission_example_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  221. $element = array();
  222. switch ($display['type']) {
  223. case 'field_permission_example_formatter':
  224. foreach ($items as $delta => $item) {
  225. $element[$delta] = array(
  226. // We wrap the fieldnote content up in a div tag.
  227. '#type' => 'html_tag',
  228. '#tag' => 'div',
  229. '#value' => check_plain($item['notes']),
  230. // Let's give the note a nice sticky-note CSS appearance.
  231. '#attributes' => array(
  232. 'class' => 'stickynote',
  233. ),
  234. // ..And this is the CSS for the stickynote.
  235. '#attached' => array(
  236. 'css' => array(drupal_get_path('module', 'field_permission_example') .
  237. '/field_permission_example.css'),
  238. ),
  239. );
  240. }
  241. break;
  242. }
  243. return $element;
  244. }
  245. /**
  246. * Implements hook_field_widget_info().
  247. *
  248. * We're implementing just one widget: A basic textarea.
  249. *
  250. * @see field_permission_example_field_widget_form()
  251. */
  252. function field_permission_example_field_widget_info() {
  253. return array(
  254. 'field_permission_example_widget' => array(
  255. 'label' => t('Field note textarea'),
  256. 'field types' => array('field_permission_example_fieldnote'),
  257. ),
  258. );
  259. }
  260. /**
  261. * Implements hook_field_widget_form().
  262. *
  263. * Drupal wants us to create a form for our field. We'll use
  264. * something very basic like a default textarea.
  265. *
  266. * @see field_permission_example_field_widget_info()
  267. */
  268. function field_permission_example_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  269. // Grab the existing value for the field.
  270. $value = isset($items[$delta]['notes']) ? $items[$delta]['notes'] : '';
  271. // Grab a reference to the form element.
  272. $widget = $element;
  273. // Set up the delta for our return element.
  274. $widget['#delta'] = $delta;
  275. // Figure out which widget we need to generate.
  276. // In our case, there's only one type.
  277. switch ($instance['widget']['type']) {
  278. case 'field_permission_example_widget':
  279. $widget += array(
  280. '#type' => 'textarea',
  281. '#default_value' => $value,
  282. );
  283. break;
  284. }
  285. $element['notes'] = $widget;
  286. return $element;
  287. }
  288. /**
  289. * Implements hook_menu().
  290. *
  291. * Provides a simple user interface that gives the developer some clues.
  292. */
  293. function field_permission_example_menu() {
  294. $items['examples/field_permission_example'] = array(
  295. 'title' => 'Field Permission Example',
  296. 'page callback' => '_field_permission_example_page',
  297. 'access callback' => TRUE,
  298. );
  299. return $items;
  300. }
  301. /**
  302. * A simple page to explain to the developer what to do.
  303. *
  304. * @see field_permission_example.module
  305. */
  306. function _field_permission_example_page() {
  307. $page = t("<p>The Field Permission Example module shows how you can restrict view and edit permissions within your field implementation. It adds a new field type called Fieldnote. Fieldnotes appear as simple text boxes on the create/edit form, and as sticky notes when viewed. By 'sticky note' we mean 'Post-It Note' but that's a trademarked term.</p><p>To see this field in action, add it to a content type or user profile. Go to the permissions page (");
  308. $page .= l(t('admin/people/permissions'), 'admin/people/permissions');
  309. $page .= t(") and look at the 'Field Permission Example' section. This allows you to change which roles can see and edit Fieldnote fields.</p><p>Creating different users with different capabilities will let you see these behaviors in action. Fieldnote helpfully displays a message telling you which permissions it is trying to resolve for the current field/user combination.</p><p>Definitely look through the code to see various implementation details.</p>");
  310. return $page;
  311. }
  312. /**
  313. * @} End of "defgroup field_permission_example".
  314. */