taxonomy_access.admin.inc 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  1. <?php
  2. /**
  3. * @file
  4. * Administrative interface for taxonomy access control.
  5. */
  6. /**
  7. * Page callback: Renders the TAC permissions administration overview page.
  8. *
  9. * @return
  10. * Form to render.
  11. *
  12. * @see taxonomy_access_menu()
  13. */
  14. function taxonomy_access_admin() {
  15. $roles = _taxonomy_access_user_roles();
  16. $active_rids = db_query(
  17. 'SELECT rid FROM {taxonomy_access_default} WHERE vid = :vid',
  18. array(':vid' => TAXONOMY_ACCESS_GLOBAL_DEFAULT)
  19. )->fetchCol();
  20. $header = array(t('Role'), t('Status'), t('Operations'));
  21. $rows = array();
  22. foreach ($roles as $rid => $name) {
  23. $row = array();
  24. $row[] = $name;
  25. if (in_array($rid, $active_rids)) {
  26. // Add edit operation link for active roles.
  27. $row[] = array('data' => t('Enabled'));
  28. }
  29. else {
  30. // Add enable link for unconfigured roles.
  31. $row[] = array('data' => t('Disabled'));
  32. }
  33. $row[] = array('data' => l(
  34. t("Configure"),
  35. TAXONOMY_ACCESS_CONFIG . "/role/$rid/edit",
  36. array('attributes' => array('class' => array('module-link', 'module-link-configure')))));
  37. $rows[] = $row;
  38. }
  39. $build['role_table'] = array(
  40. '#theme' => 'table',
  41. '#header' => $header,
  42. '#rows' => $rows,
  43. );
  44. return $build;
  45. }
  46. /**
  47. * Form constructor for a form to to delete access rules for a particular role.
  48. *
  49. * @param int $rid
  50. * The role ID to disable.
  51. *
  52. * @see taxonomy_access_role_delete_confirm_submit()
  53. * @see taxonomy_access_menu()
  54. * @ingroup forms
  55. */
  56. function taxonomy_access_role_delete_confirm($form, &$form_state, $rid) {
  57. $roles = _taxonomy_access_user_roles();
  58. if (taxonomy_access_role_enabled($rid)) {
  59. $form['rid'] = array(
  60. '#type' => 'value',
  61. '#value' => $rid,
  62. );
  63. return confirm_form($form,
  64. t("Are you sure you want to delete all taxonomy access rules for the role %role?",
  65. array('%role' => $roles[$rid])),
  66. TAXONOMY_ACCESS_CONFIG . '/role/%/edit',
  67. t('This action cannot be undone.'),
  68. t('Delete all'),
  69. t('Cancel'));
  70. }
  71. }
  72. /**
  73. * Form submission handler for taxonomy_role_delete_confirm().
  74. */
  75. function taxonomy_access_role_delete_confirm_submit($form, &$form_state) {
  76. $roles = _taxonomy_access_user_roles();
  77. $rid = $form_state['values']['rid'];
  78. if (is_numeric($rid)
  79. && $rid != DRUPAL_ANONYMOUS_RID
  80. && $rid != DRUPAL_AUTHENTICATED_RID) {
  81. if ($form_state['values']['confirm']) {
  82. $form_state['redirect'] = TAXONOMY_ACCESS_CONFIG;
  83. taxonomy_access_delete_role_grants($rid);
  84. drupal_set_message(t('All taxonomy access rules deleted for role %role.',
  85. array('%role' => $roles[$rid])));
  86. }
  87. }
  88. }
  89. /**
  90. * Generates a URL to enable a role with a token for CSRF protection.
  91. *
  92. * @param int $rid
  93. * The role ID.
  94. *
  95. * @return string
  96. * The full URL for the request path.
  97. */
  98. function taxonomy_access_enable_role_url($rid) {
  99. // Create a query array with a token to validate the sumbission.
  100. $query = drupal_get_destination();
  101. $query['token'] = drupal_get_token($rid);
  102. // Build and return the URL with the token and destination.
  103. return url(
  104. TAXONOMY_ACCESS_CONFIG . "/role/$rid/enable",
  105. array('query' => $query)
  106. );
  107. }
  108. /**
  109. * Page callback: Enables a role if the proper token is provided.
  110. *
  111. * @param int $rid
  112. * The role ID.
  113. */
  114. function taxonomy_access_enable_role_validate($rid) {
  115. $rid = intval($rid);
  116. // If a valid token is not provided, return a 403.
  117. $query = drupal_get_query_parameters();
  118. if (empty($query['token']) || !drupal_valid_token($query['token'], $rid)) {
  119. return MENU_ACCESS_DENIED;
  120. }
  121. // Return a 404 for the anonymous or authenticated roles.
  122. if (in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
  123. return MENU_NOT_FOUND;
  124. }
  125. // Return a 404 for invalid role IDs.
  126. $roles = _taxonomy_access_user_roles();
  127. if (empty($roles[$rid])) {
  128. return MENU_NOT_FOUND;
  129. }
  130. // If the parameters pass validation, enable the role and complete redirect.
  131. if (taxonomy_access_enable_role($rid)) {
  132. drupal_set_message(t('Role %name enabled successfully.',
  133. array('%name' => $roles[$rid])));
  134. }
  135. drupal_goto();
  136. }
  137. /**
  138. * Form constructor for a form to manage grants by role.
  139. *
  140. * @param int $rid
  141. * The role ID.
  142. *
  143. * @see taxonomy_access_admin_form_submit()
  144. * @see taxonomy_access_menu()
  145. * @ingroup forms
  146. */
  147. function taxonomy_access_admin_role($form, $form_state, $rid) {
  148. // Always include the role ID in the form.
  149. $rid = intval($rid);
  150. $form['rid'] = array('#type' => 'value', '#value' => $rid);
  151. // For custom roles, allow the user to enable or disable grants for the role.
  152. if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
  153. $roles = _taxonomy_access_user_roles();
  154. // If the role is not enabled, return only a link to enable it.
  155. if (!taxonomy_access_role_enabled($rid)) {
  156. $form['status'] = array(
  157. '#markup' => '<p>' . t(
  158. 'Access control for the %name role is disabled. <a href="@url">Enable @name</a>.',
  159. array(
  160. '%name' => $roles[$rid],
  161. '@name' => $roles[$rid],
  162. '@url' => taxonomy_access_enable_role_url($rid))) . '</p>'
  163. );
  164. return $form;
  165. }
  166. // Otherwise, add a link to disable and build the rest of the form.
  167. else {
  168. $disable_url = url(
  169. TAXONOMY_ACCESS_CONFIG . "/role/$rid/delete",
  170. array('query' => drupal_get_destination())
  171. );
  172. $form['status'] = array(
  173. '#markup' => '<p>' . t(
  174. 'Access control for the %name role is enabled. <a href="@url">Disable @name</a>.',
  175. array('@name' => $roles[$rid], '%name' => $roles[$rid], '@url' => $disable_url)) . '</p>'
  176. );
  177. }
  178. }
  179. // Retrieve role grants and display an administration form.
  180. // Disable list filtering while preparing this form.
  181. taxonomy_access_disable_list();
  182. // Fetch all grants for the role.
  183. $defaults =
  184. db_query(
  185. 'SELECT vid, grant_view, grant_update, grant_delete, grant_create,
  186. grant_list
  187. FROM {taxonomy_access_default}
  188. WHERE rid = :rid',
  189. array(':rid' => $rid))
  190. ->fetchAllAssoc('vid', PDO::FETCH_ASSOC);
  191. $records =
  192. db_query(
  193. 'SELECT ta.tid, td.vid, ta.grant_view, ta.grant_update, ta.grant_delete,
  194. ta.grant_create, ta.grant_list
  195. FROM {taxonomy_access_term} ta
  196. INNER JOIN {taxonomy_term_data} td ON ta.tid = td.tid
  197. WHERE rid = :rid',
  198. array(':rid' => $rid))
  199. ->fetchAllAssoc('tid', PDO::FETCH_ASSOC);
  200. $term_grants = array();
  201. foreach ($records as $record) {
  202. $term_grants[$record['vid']][$record['tid']] = $record;
  203. }
  204. // Add a fieldset for the global default.
  205. $form['global_default'] = array(
  206. '#type' => 'fieldset',
  207. '#title' => t('Global default'),
  208. '#description' => t('The global default controls access to untagged nodes. It is also used as the default for disabled vocabularies.'),
  209. '#collapsible' => TRUE,
  210. // Collapse if there are vocabularies configured.
  211. '#collapsed' => (sizeof($defaults) > 1),
  212. );
  213. // Print term grant table.
  214. $form['global_default']['grants'] = taxonomy_access_grant_add_table($defaults[TAXONOMY_ACCESS_GLOBAL_DEFAULT], TAXONOMY_ACCESS_VOCABULARY_DEFAULT);
  215. // Fetch all vocabularies and determine which are enabled for the role.
  216. $vocabs = array();
  217. $disabled = array();
  218. foreach (taxonomy_get_vocabularies() as $vocab) {
  219. $vocabs[$vocab->vid] = $vocab;
  220. if (!isset($defaults[$vocab->vid])) {
  221. $disabled[$vocab->vid] = $vocab->name;
  222. }
  223. }
  224. // Add a fieldset to enable vocabularies.
  225. if (!empty($disabled)) {
  226. $form['enable_vocabs'] = array(
  227. '#type' => 'fieldset',
  228. '#collapsible' => TRUE,
  229. '#collapsed' => TRUE,
  230. '#title' => t('Add vocabulary'),
  231. '#attributes' => array('class' => array('container-inline', 'taxonomy-access-add')),
  232. );
  233. $form['enable_vocabs']['enable_vocab'] = array(
  234. '#type' => 'select',
  235. '#title' => t('Vocabulary'),
  236. '#options' => $disabled,
  237. );
  238. $form['enable_vocabs']['add'] = array(
  239. '#type' => 'submit',
  240. '#submit' => array('taxonomy_access_enable_vocab_submit'),
  241. '#value' => t('Add'),
  242. );
  243. }
  244. // Add a fieldset for each enabled vocabulary.
  245. foreach ($defaults as $vid => $vocab_default) {
  246. if (!empty($vocabs[$vid])) {
  247. $vocab = $vocabs[$vid];
  248. $name = $vocab->machine_name;
  249. // Fetch unconfigured terms and reorder term records by hierarchy.
  250. $sort = array();
  251. $add_options = array();
  252. if ($tree = taxonomy_get_tree($vid)) {
  253. foreach ($tree as $term) {
  254. if (empty($term_grants[$vid][$term->tid])) {
  255. $add_options["term $term->tid"] = str_repeat('-', $term->depth) . ' ' .check_plain($term->name);
  256. }
  257. else {
  258. $sort[$term->tid] = $term_grants[$vid][$term->tid];
  259. $sort[$term->tid]['name'] = str_repeat('-', $term->depth) . ' ' . check_plain($term->name);
  260. }
  261. }
  262. $term_grants[$vid] = $sort;
  263. }
  264. $grants = array(TAXONOMY_ACCESS_VOCABULARY_DEFAULT => $vocab_default);
  265. $grants[TAXONOMY_ACCESS_VOCABULARY_DEFAULT]['name'] = t('Default');
  266. if (!empty($term_grants[$vid])) {
  267. $grants += $term_grants[$vid];
  268. }
  269. $form[$name] = array(
  270. '#type' => 'fieldset',
  271. '#title' => $vocab->name,
  272. '#attributes' => array('class' => array('taxonomy-access-vocab')),
  273. '#description' => t('The default settings apply to all terms in %vocab that do not have their own below.', array('%vocab' => $vocab->name)),
  274. '#collapsible' => TRUE,
  275. '#collapsed' => FALSE,
  276. );
  277. // Term grant table.
  278. $form[$name]['grants'] =
  279. taxonomy_access_grant_table($grants, $vocab->vid, t('Term'), !empty($term_grants[$vid]));
  280. // Fieldset to add a new term if there are any.
  281. if (!empty($add_options)) {
  282. $form[$name]['new'] = array(
  283. '#type' => 'fieldset',
  284. '#collapsible' => TRUE,
  285. '#collapsed' => TRUE,
  286. '#title' => t('Add term'),
  287. '#tree' => TRUE,
  288. '#attributes' => array('class' => array('container-inline', 'taxonomy-access-add')),
  289. );
  290. $form[$name]['new'][$vid]['item'] = array(
  291. '#type' => 'select',
  292. '#title' => t('Term'),
  293. '#options' => $add_options,
  294. );
  295. $form[$name]['new'][$vid]['recursive'] = array(
  296. '#type' => 'checkbox',
  297. '#title' => t('with descendants'),
  298. );
  299. $form[$name]['new'][$vid]['grants'] =
  300. taxonomy_access_grant_add_table($vocab_default, $vid);
  301. $form[$name]['new'][$vid]['add'] = array(
  302. '#type' => 'submit',
  303. '#name' => $vid,
  304. '#submit' => array('taxonomy_access_add_term_submit'),
  305. '#value' => t('Add'),
  306. );
  307. }
  308. $disable_url = url(
  309. TAXONOMY_ACCESS_CONFIG . "/role/$rid/disable/$vid",
  310. array('query' => drupal_get_destination())
  311. );
  312. $form[$name]['disable'] = array(
  313. '#markup' => '<p>' . t(
  314. 'To disable the %vocab vocabulary, <a href="@url">delete all @vocab access rules</a>.',
  315. array('%vocab' => $vocab->name, '@vocab' => $vocab->name, '@url' => $disable_url)) . '</p>'
  316. );
  317. }
  318. }
  319. $form['actions'] = array('#type' => 'actions');
  320. $form['actions']['submit'] = array(
  321. '#type' => 'submit',
  322. '#value' => t('Save all'),
  323. '#submit' => array('taxonomy_access_save_all_submit'),
  324. );
  325. if (!empty($term_grants)) {
  326. $form['actions']['delete'] = array(
  327. '#type' => 'submit',
  328. '#value' => t('Delete selected'),
  329. '#submit' => array('taxonomy_access_delete_selected_submit'),
  330. );
  331. }
  332. return $form;
  333. }
  334. /**
  335. * Generates a grant table for multiple access rules.
  336. *
  337. * @param array $rows
  338. * An array of grant row data, keyed by an ID (term, vocab, role, etc.). Each
  339. * row should include the following keys:
  340. * - name: (optional) The label for the row (e.g., a term, vocabulary, or
  341. * role name).
  342. * - view: The View grant value select box for the element.
  343. * - update: The Update grant value select box for the element.
  344. * - delete: The Delete grant value select box for the element.
  345. * - create: The Add tag grant value select box for the element.
  346. * - list: The View tag grant value select box for the element.
  347. * @param int $parent_vid
  348. * The parent ID for the table in the form tree structure (typically a
  349. * vocabulary id).
  350. * @param string $first_col
  351. * The header for the first column (in the 'name' key for each row).
  352. * @param bool $delete
  353. * (optional) Whether to add a deletion checkbox to each row along with a
  354. * "Check all" box in the table header. The checbox is automatically disabled
  355. * for TAXONOMY_ACCESS_VOCABULARY_DEFAULT. Defaults to TRUE.
  356. *
  357. * @return
  358. * Renderable array containing the table.
  359. *
  360. * @see taxonomy_access_grant_table()
  361. */
  362. function taxonomy_access_grant_table(array $rows, $parent_vid, $first_col, $delete = TRUE) {
  363. $header = taxonomy_access_grant_table_header();
  364. if ($first_col) {
  365. array_unshift(
  366. $header,
  367. array('data' => $first_col, 'class' => array('taxonomy-access-label'))
  368. );
  369. }
  370. if ($delete) {
  371. drupal_add_js('misc/tableselect.js');
  372. array_unshift($header, array('class' => array('select-all')));
  373. }
  374. $table = array(
  375. '#type' => 'taxonomy_access_grant_table',
  376. '#tree' => TRUE,
  377. '#header' => $header,
  378. );
  379. foreach ($rows as $id => $row) {
  380. $table[$parent_vid][$id] = taxonomy_access_admin_build_row($row, 'name', $delete);
  381. }
  382. // Disable the delete checkbox for the default.
  383. if ($delete && isset($table[$parent_vid][TAXONOMY_ACCESS_VOCABULARY_DEFAULT])) {
  384. $table[$parent_vid][TAXONOMY_ACCESS_VOCABULARY_DEFAULT]['remove']['#disabled'] = TRUE;
  385. }
  386. return $table;
  387. }
  388. /**
  389. * Generates a grant table for adding access rules with one set of values.
  390. *
  391. * @param array $rows
  392. * An associative array of access rule data, with the following keys:
  393. * - view: The View grant value select box for the element.
  394. * - update: The Update grant value select box for the element.
  395. * - delete: The Delete grant value select box for the element.
  396. * - create: The Add tag grant value select box for the element.
  397. * - list: The View tag grant value select box for the element.
  398. * @param int $id
  399. * The ID for this set (e.g., a vocabulary ID).
  400. *
  401. * @return
  402. * Renderable array containing the table.
  403. *
  404. * @see taxonomy_access_grant_table()
  405. */
  406. function taxonomy_access_grant_add_table($row, $id) {
  407. $header = taxonomy_access_grant_table_header();
  408. $table = array(
  409. '#type' => 'taxonomy_access_grant_table',
  410. '#tree' => TRUE,
  411. '#header' => $header,
  412. );
  413. $table[$id][TAXONOMY_ACCESS_VOCABULARY_DEFAULT] = taxonomy_access_admin_build_row($row);
  414. return $table;
  415. }
  416. /**
  417. * Returns a header array for grant form tables.
  418. *
  419. * @return array
  420. * An array of header cell data for a grant table.
  421. */
  422. function taxonomy_access_grant_table_header() {
  423. $header = array(
  424. array('data' => t('View')),
  425. array('data' => t('Update')),
  426. array('data' => t('Delete')),
  427. array('data' => t('Add Tag')),
  428. array('data' => t('View Tag')),
  429. );
  430. foreach ($header as &$cell) {
  431. $cell['class'] = array('taxonomy-access-grant');
  432. }
  433. return $header;
  434. }
  435. /**
  436. * Theme our grant table.
  437. *
  438. * @todo
  439. * Use a separate theme function for taxonomy_access_grant_add_table() to get
  440. * out of nesting hell?
  441. * @todo
  442. * I clearly have no idea what I'm doing here.
  443. */
  444. function theme_taxonomy_access_grant_table($element_data) {
  445. $table = array();
  446. $table['header'] = $element_data['elements']['#header'];
  447. $table['attributes']['class'] = array('taxonomy-access-grant-table');
  448. $rows = array();
  449. foreach (element_children($element_data['elements']) as $element_key) {
  450. $child = $element_data['elements'][$element_key];
  451. foreach (element_children($child) as $child_key) {
  452. $record = $child[$child_key];
  453. $row = array();
  454. foreach (element_children($record) as $record_key) {
  455. $data = array('data' => $record[$record_key]);
  456. // If it's the default, add styling.
  457. if ($record_key == 'name') {
  458. $data['class'] = array('taxonomy-access-label');
  459. if ($child_key == TAXONOMY_ACCESS_VOCABULARY_DEFAULT) {
  460. $data['class'][] = 'taxonomy-access-default';
  461. }
  462. }
  463. // Add grant classes to grant cells.
  464. elseif (in_array($record_key, array('view', 'update', 'delete', 'create', 'list'))) {
  465. $grant_class = $record_key . '-' . $data['data']['#default_value'];
  466. $data['class'] = array('taxonomy-access-grant', $grant_class);
  467. }
  468. $row[] = $data;
  469. }
  470. $rows[] = $row;
  471. }
  472. }
  473. $table['rows'] = $rows;
  474. return theme('table', $table);
  475. }
  476. /**
  477. * Assembles a row of grant options for a term or default on the admin form.
  478. *
  479. * @param array $grants
  480. * An array of grants to use as form defaults.
  481. * @param $label_key
  482. * (optional) Key of the column to use as a label in each grant row. Defaults
  483. * to NULL.
  484. */
  485. function taxonomy_access_admin_build_row(array $grants, $label_key = NULL, $delete = FALSE) {
  486. $form['#tree'] = TRUE;
  487. if ($delete) {
  488. $form['remove'] = array(
  489. '#type' => 'checkbox',
  490. '#title' => t('Delete access rule for @name', array('@name' => $grants[$label_key])),
  491. '#title_display' => 'invisible',
  492. );
  493. }
  494. if ($label_key) {
  495. $form[$label_key] = array(
  496. '#type' => 'markup',
  497. '#markup' => check_plain($grants[$label_key]),
  498. );
  499. }
  500. foreach (array('view', 'update', 'delete', 'create', 'list') as $grant) {
  501. $for = $label_key ? $grants[$label_key] : NULL;
  502. $form[$grant] = array(
  503. '#type' => 'select',
  504. '#title' => _taxonomy_access_grant_field_label($grant, $for),
  505. '#title_display' => 'invisible',
  506. '#default_value' => is_string($grants['grant_' . $grant]) ? $grants['grant_' . $grant] : TAXONOMY_ACCESS_NODE_IGNORE,
  507. '#required' => TRUE,
  508. );
  509. }
  510. foreach (array('view', 'update', 'delete') as $grant) {
  511. $form[$grant]['#options'] = array(
  512. TAXONOMY_ACCESS_NODE_ALLOW => t('Allow'),
  513. TAXONOMY_ACCESS_NODE_IGNORE => t('Ignore'),
  514. TAXONOMY_ACCESS_NODE_DENY => t('Deny'),
  515. );
  516. }
  517. foreach (array('create', 'list') as $grant) {
  518. $form[$grant]['#options'] = array(
  519. TAXONOMY_ACCESS_TERM_ALLOW => t('Allow'),
  520. TAXONOMY_ACCESS_TERM_DENY => t('Deny'),
  521. );
  522. }
  523. return $form;
  524. }
  525. /**
  526. * Returns the proper invisible field label for each grant table element.
  527. */
  528. function _taxonomy_access_grant_field_label($grant, $for = NULL) {
  529. if ($for) {
  530. $label = array('@label', $for);
  531. $titles = array(
  532. 'view' => t('View grant for @label', $label),
  533. 'update' => t('Update grant for @label', $label),
  534. 'delete' => t('Delete grant for @label', $label),
  535. 'create' => t('Add tag grant for @label', $label),
  536. 'list' => t('View tag grant for @label', $label),
  537. );
  538. }
  539. else {
  540. $titles = array(
  541. 'view' => t('View grant'),
  542. 'update' => t('Update grant'),
  543. 'delete' => t('Delete grant'),
  544. 'create' => t('Add tag grant'),
  545. 'list' => t('View tag grant'),
  546. );
  547. }
  548. return $titles[$grant];
  549. }
  550. /**
  551. * Form submission handler for taxonomy_access_admin_role().
  552. *
  553. * Processes submissions for the vocabulary 'Add' button.
  554. */
  555. function taxonomy_access_enable_vocab_submit($form, &$form_state) {
  556. $rid = $form_state['values']['rid'];
  557. $vid = $form_state['values']['enable_vocab'];
  558. $roles = _taxonomy_access_user_roles();
  559. $vocab = taxonomy_vocabulary_load($vid);
  560. if (taxonomy_access_enable_vocab($vid, $rid)) {
  561. drupal_set_message(t(
  562. 'Vocabulary %vocab enabled successfully for the %role role.',
  563. array(
  564. '%vocab' => $vocab->name,
  565. '%role' => $roles[$rid])));
  566. }
  567. else {
  568. drupal_set_message(t('The vocabulary could not be enabled.'), 'error');
  569. }
  570. }
  571. /**
  572. * Form submission handler for taxonomy_access_admin_role().
  573. *
  574. * Processes submissions for the term 'Add' button.
  575. */
  576. function taxonomy_access_add_term_submit($form, &$form_state) {
  577. $vid = $form_state['clicked_button']['#name'];
  578. $new = $form_state['values']['new'][$vid];
  579. $rid = $form_state['values']['rid'];
  580. list($type, $id) = explode(' ', $new['item']);
  581. $rows = array();
  582. $rows[$id] =
  583. _taxonomy_access_format_grant_record($id, $rid, $new['grants'][$vid][TAXONOMY_ACCESS_VOCABULARY_DEFAULT]);
  584. // If we are adding children recursively, add those as well.
  585. if ($new['recursive'] == 1) {
  586. $children = _taxonomy_access_get_descendants($id);
  587. foreach ($children as $tid) {
  588. $rows[$tid] =
  589. _taxonomy_access_format_grant_record($tid, $rid, $new['grants'][$vid][TAXONOMY_ACCESS_VOCABULARY_DEFAULT]);
  590. }
  591. }
  592. // Set the grants for the row or rows.
  593. taxonomy_access_set_term_grants($rows);
  594. }
  595. /**
  596. * Page callback: Returns a confirmation form to disable a vocabulary.
  597. *
  598. * @param int $rid
  599. * The role ID.
  600. * @param object $vocab
  601. * The vocabulary object.
  602. *
  603. * @todo
  604. * Check if vocab is enabled and return a 404 otherwise?
  605. *
  606. * @see taxonomy_access_menu()
  607. * @see taxonomy_access_admin_role().
  608. * @see taxonomy_access_disable_vocab_confirm_page()
  609. */
  610. function taxonomy_access_disable_vocab_confirm_page($rid, $vocab) {
  611. $rid = intval($rid);
  612. // Return a 404 on invalid vid or rid.
  613. if (!$vocab->vid || !$rid) {
  614. return MENU_NOT_FOUND;
  615. }
  616. return drupal_get_form('taxonomy_access_disable_vocab_confirm', $rid, $vocab);
  617. }
  618. /**
  619. * Returns a confirmation form for disabling a vocabulary for a role.
  620. *
  621. * @param int $rid
  622. * The role ID.
  623. * @param object $vocab
  624. * The vocabulary object.
  625. *
  626. * @see taxonomy_access_disable_vocab_confirm_page()
  627. * @see taxonomy_access_disable_vocab_confirm_submit()
  628. * @ingroup forms
  629. */
  630. function taxonomy_access_disable_vocab_confirm($form, &$form_state, $rid, $vocab) {
  631. $roles = _taxonomy_access_user_roles();
  632. if (taxonomy_access_role_enabled($rid)) {
  633. $form['rid'] = array(
  634. '#type' => 'value',
  635. '#value' => $rid,
  636. );
  637. $form['vid'] = array(
  638. '#type' => 'value',
  639. '#value' => $vocab->vid,
  640. );
  641. $form['vocab_name'] = array(
  642. '#type' => 'value',
  643. '#value' => $vocab->name,
  644. );
  645. return confirm_form($form,
  646. t("Are you sure you want to delete all Taxonomy access rules for %vocab in the %role role?",
  647. array('%role' => $roles[$rid], '%vocab' => $vocab->name)),
  648. TAXONOMY_ACCESS_CONFIG . '/role/%/edit',
  649. t('This action cannot be undone.'),
  650. t('Delete all'),
  651. t('Cancel'));
  652. }
  653. }
  654. /**
  655. * Form submission handler for taxonomy_access_disable_vocab_confirm().
  656. *
  657. * @param int $rid
  658. * The role ID to disable.
  659. *
  660. * @todo
  661. * Set a message on invalid $rid or $vid?
  662. */
  663. function taxonomy_access_disable_vocab_confirm_submit($form, &$form_state) {
  664. $roles = _taxonomy_access_user_roles();
  665. $rid = intval($form_state['values']['rid']);
  666. $vid = intval($form_state['values']['vid']);
  667. // Do not proceed for invalid role IDs, and do not allow the global default
  668. // to be deleted.
  669. if (!$vid || !$rid || empty($roles[$rid])) {
  670. return FALSE;
  671. }
  672. if ($form_state['values']['confirm']) {
  673. $form_state['redirect'] = TAXONOMY_ACCESS_CONFIG;
  674. if (taxonomy_access_disable_vocab($vid, $rid)) {
  675. drupal_set_message(
  676. t('All Taxonomy access rules deleted for %vocab in role %role.',
  677. array(
  678. '%vocab' => $form_state['values']['vocab_name'],
  679. '%role' => $roles[$rid])
  680. ));
  681. return TRUE;
  682. }
  683. }
  684. }
  685. /**
  686. * Form submission handler for taxonomy_access_admin_role().
  687. *
  688. * Processes submissions for the "Delete selected" button.
  689. *
  690. * @todo
  691. * The parent form could probably be refactored to make this more efficient
  692. * (by putting these elements in a flat list) but that would require changing
  693. * taxonomy_access_grant_table() and taxonomy_access_build_row().
  694. */
  695. function taxonomy_access_delete_selected_submit($form, &$form_state) {
  696. $rid = intval($form_state['values']['rid']);
  697. $delete_tids = array();
  698. foreach ($form_state['values']['grants'] as $vid => $tids) {
  699. foreach ($tids as $tid => $record) {
  700. if (!empty($record['remove'])) {
  701. $delete_tids[] = $tid;
  702. }
  703. }
  704. }
  705. if ($rid) {
  706. if (taxonomy_access_delete_term_grants($delete_tids, $rid)) {
  707. drupal_set_message(format_plural(
  708. sizeof($delete_tids),
  709. '1 term access rule was deleted.',
  710. '@count term access rules were deleted.'));
  711. }
  712. else {
  713. drupal_set_message(t('The records could not be deleted.'), 'warning');
  714. }
  715. }
  716. }
  717. /**
  718. * Form submission handler for taxonomy_access_admin_form().
  719. *
  720. * Processes submissions for the 'Save all' button.
  721. */
  722. function taxonomy_access_save_all_submit($form, &$form_state) {
  723. $values = $form_state['values'];
  724. $rid = $values['rid'];
  725. $vocabs = taxonomy_get_vocabularies();
  726. // Create four lists of records to update.
  727. $update_terms = array();
  728. $skip_terms = array();
  729. $update_defaults = array();
  730. $skip_defaults = array();
  731. foreach ($values['grants'] as $vid => $rows) {
  732. if ($vid == TAXONOMY_ACCESS_GLOBAL_DEFAULT) {
  733. $element = $form['global_default'];
  734. }
  735. else {
  736. $vocab = $vocabs[$vid];
  737. $element = $form[$vocab->machine_name];
  738. }
  739. foreach ($rows as $tid => $row) {
  740. // Check the default values for this row.
  741. $defaults = array();
  742. $grants = array();
  743. foreach (array('view', 'update', 'delete', 'create', 'list') as $grant_name) {
  744. $grants[$grant_name] = $row[$grant_name];
  745. $defaults[$grant_name] =
  746. $element['grants'][$vid][$tid][$grant_name]['#default_value'];
  747. }
  748. // Proceed if the user changed the row (values differ from defaults).
  749. if ($defaults != $grants) {
  750. // If the grants for node access match the defaults, then we
  751. // can skip updating node access records for this row.
  752. $update_nodes = FALSE;
  753. foreach (array('view', 'update', 'delete') as $op) {
  754. if ($defaults[$op] != $grants[$op]) {
  755. $update_nodes = TRUE;
  756. }
  757. }
  758. // Add the row to one of the four arrays.
  759. switch (TRUE) {
  760. // Term record with node grant changes.
  761. case ($tid && $update_nodes):
  762. $update_terms[$tid] =
  763. _taxonomy_access_format_grant_record($tid, $rid, $grants);
  764. break;
  765. // Term record and no node grant changes.
  766. case ($tid && !$update_nodes):
  767. $skip_terms[$tid] =
  768. _taxonomy_access_format_grant_record($tid, $rid, $grants);
  769. break;
  770. // Vocab record with node grant changes.
  771. case (!$tid && $update_nodes):
  772. $update_defaults[$vid] =
  773. _taxonomy_access_format_grant_record($vid, $rid, $grants, TRUE);
  774. break;
  775. // Vocab record and no node grant changes.
  776. case (!$tid && !$update_nodes):
  777. $skip_defaults[$vid] =
  778. _taxonomy_access_format_grant_record($vid, $rid, $grants, TRUE);
  779. break;
  780. }
  781. }
  782. }
  783. }
  784. // Process each set.
  785. if (!empty($update_terms)) {
  786. taxonomy_access_set_term_grants($update_terms);
  787. }
  788. if (!empty($skip_terms)) {
  789. taxonomy_access_set_term_grants($skip_terms, FALSE);
  790. }
  791. if (!empty($update_defaults)) {
  792. taxonomy_access_set_default_grants($update_defaults);
  793. }
  794. if (!empty($skip_defaults)) {
  795. taxonomy_access_set_default_grants($skip_defaults, FALSE);
  796. }
  797. }
  798. /**
  799. * Generates HTML markup with form instructions for the admin form.
  800. *
  801. * @return
  802. * Instructions HTML string.
  803. */
  804. function _taxonomy_access_admin_instructions_html() {
  805. $instructions = '';
  806. $instructions .= ''
  807. . "<br /><br />"
  808. . "<div class=\"instructions\">"
  809. . "<h2>" . t("Explanation of fields") . "</h2>"
  810. . _taxonomy_access_grant_help_table()
  811. . "<p>"
  812. . t('Options for View, Update, and Delete are <em>Allow</em> (<acronym title="Allow">A</acronym>), <em>Ignore</em> (<acronym title="Ignore">I</acronym>), and <em>Deny</em> (<acronym title="Deny">D</acronym>).')
  813. . "</p>\n\n"
  814. . "<ul>\n"
  815. . "<li>"
  816. . t('<em>Deny</em> (<acronym title="Deny">D</acronym>) overrides <em>Allow</em> (<acronym title="Allow">A</acronym>) within this role.')
  817. . "</li>"
  818. . "<li>"
  819. . t('Both <em>Allow</em> (<acronym title="Allow">A</acronym>) and <em>Deny</em> (<acronym title="Deny">D</acronym>) override <em>Ignore</em> (<acronym title="Ignore">I</acronym>) within this role.')
  820. . "</li>"
  821. . "<li>"
  822. . t('If a user has <strong>multiple roles</strong>, an <em>Allow</em> (<acronym title="Allow">A</acronym>) from another role <strong>will</strong> override a <em>Deny</em> (<acronym title="Deny">D</acronym>) here.')
  823. . "</li>"
  824. . "</ul>\n\n"
  825. ;
  826. if (arg(4) != DRUPAL_ANONYMOUS_RID && arg(4) != DRUPAL_AUTHENTICATED_RID) {
  827. // Role other than Anonymous or Authenticated
  828. $instructions .= ''
  829. . "<p>"
  830. . t('<strong>Remember:</strong> This role <strong>will</strong> inherit permissions from the <em>authenticated user</em> role. Be sure to <a href="@url">configure the authenticated user</a> properly.',
  831. array("@url" => url(
  832. TAXONOMY_ACCESS_CONFIG
  833. . "/role/"
  834. . DRUPAL_AUTHENTICATED_RID
  835. . '/edit')))
  836. . "</p>\n\n"
  837. ;
  838. }
  839. $instructions .= ''
  840. . "<p>"
  841. . t('For more information and for troubleshooting guidelines, see the <a href="@help">help page</a> and the !readme.',
  842. array(
  843. '@help' => url('admin/help/taxonomy_access'),
  844. '!readme' => "<code>README.txt</code>"
  845. ))
  846. . "</p>\n\n"
  847. . "</div>\n\n"
  848. ;
  849. return $instructions;
  850. }