fpa.theme.inc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  1. <?php
  2. /**
  3. * @file
  4. * Theme callbacks to pre-tag rows for FPA functionality.
  5. */
  6. /**
  7. * Implements hook_theme().
  8. */
  9. function fpa_theme($existing, $type, $theme, $path) {
  10. return array(
  11. 'fpa_user_admin_permissions' => array(
  12. 'render element' => 'form',
  13. 'file' => 'fpa.theme.inc',
  14. ),
  15. );
  16. }
  17. /**
  18. * Theme function to pre-mark rows with FPA attributes.
  19. *
  20. * Based on Drupal Core's permissions form theme function.
  21. *
  22. * @see theme_user_admin_permissions().
  23. */
  24. function theme_fpa_user_admin_permissions($variables) {
  25. $form = $variables['form'];
  26. $nameless_checkbox = array(
  27. '#type' => 'html_tag',
  28. '#tag' => 'input',
  29. '#attributes' => array(
  30. 'type' => 'checkbox',
  31. 'class' => array(
  32. 'rid-1', // Prevents Drupal core Drupal.behaviors.permissions.toggle from applying.
  33. 'form-checkbox',
  34. 'fpa-checkboxes-toggle',
  35. ),
  36. ),
  37. );
  38. $nameless_checkbox_output = drupal_render($nameless_checkbox);
  39. $dummy_checkbox = array(
  40. '#type' => 'html_tag',
  41. '#tag' => 'input',
  42. '#attributes' => array(
  43. 'type' => 'checkbox',
  44. 'disabled' => 'disabled',
  45. 'checked' => 'checked',
  46. 'title' => t('This permission is inherited from the authenticated user role.'),
  47. 'class' => array(
  48. 'dummy-checkbox',
  49. ),
  50. ),
  51. );
  52. $dummy_checkbox_output = drupal_render($dummy_checkbox);
  53. $permission_col_template = array(
  54. '#type' => 'container',
  55. '#attributes' => array(
  56. 'class' => array(
  57. 'fpa-permission-container',
  58. ),
  59. ),
  60. 'description' => array(
  61. '#markup' => '',
  62. ),
  63. 'checkbox_cell' => array(
  64. '#type' => 'container',
  65. '#attributes' => array(
  66. 'class' => array(
  67. 'fpa-row-toggle-container',
  68. ),
  69. ),
  70. 'checkbox_form_item' => array(
  71. '#type' => 'container',
  72. '#attributes' => array(
  73. 'title' => t('Toggle visible checkboxes in this row.'),
  74. 'class' => array(
  75. 'form-item',
  76. 'form-type-checkbox',
  77. ),
  78. ),
  79. 'label' => array(
  80. '#type' => 'html_tag',
  81. '#tag' => 'label',
  82. '#attributes' => array(
  83. 'class' => array(
  84. 'element-invisible',
  85. ),
  86. ),
  87. '#value' => 'test',
  88. ),
  89. 'checkbox' => array(
  90. '#markup' => $nameless_checkbox_output,
  91. ),
  92. ),
  93. ),
  94. );
  95. $checkboxes_children = element_children($form['checkboxes']);
  96. // Prepare role names processed by drupal_html_class() ahead of time.
  97. $roles_attr_values = array();
  98. foreach ($checkboxes_children as $rid) {
  99. $roles_attr_values[$rid] = drupal_html_class($form['role_names'][$rid]['#markup']);
  100. }
  101. $first_role_index = array_shift($checkboxes_children);
  102. // Lists for wrapper.
  103. $modules = array();
  104. $user_roles = array();
  105. // Index of current module row.
  106. $module = NULL;
  107. // Row counter.
  108. $i = 0;
  109. $rows = array();
  110. // Iterate over rows in form table.
  111. foreach (element_children($form['permission']) as $key) {
  112. // Row template.
  113. $row = array(
  114. 'data' => array(), // Array of table cells.
  115. 'title' => array(), // HTML attribute on table row tag.
  116. FPA_ATTR_MODULE => array(), // HTML attribute on table row tag.
  117. FPA_ATTR_PERMISSION => array(), // HTML attribute on table row tag.
  118. FPA_ATTR_CHECKED => array(),
  119. FPA_ATTR_NOT_CHECKED => array(),
  120. );
  121. // Determine if row is module or permission.
  122. if (is_numeric($key)) {
  123. // Module row.
  124. $row['class'][] = 'fpa-module-row';
  125. // Mark current row with escaped module name.
  126. $row[FPA_ATTR_MODULE] = array(
  127. // System name
  128. 0 => $form['permission'][$key]['#id'],
  129. // Readable name
  130. 1 => strip_tags($form['permission'][$key]['#markup']),
  131. );
  132. // Readable
  133. $row['data'][] = array(
  134. 'data' => drupal_render($form['permission'][$key]),
  135. 'class' => array('module'),
  136. 'id' => 'module-' . $form['permission'][$key]['#id'],
  137. 'colspan' => count($form['role_names']['#value']) + 1,
  138. );
  139. $row['title'] = array($form['permission'][$key]['#id']);
  140. $row[FPA_ATTR_SYSTEM_NAME] = $row[FPA_ATTR_MODULE][0];
  141. $row[FPA_ATTR_MODULE] = array_unique(array_map('drupal_html_class', $row[FPA_ATTR_MODULE]));
  142. // Add modules to left-side modules list.
  143. $modules[$row[FPA_ATTR_MODULE][0]] = array(
  144. 'text' => strip_tags($form['permission'][$key]['#markup']),
  145. 'title' => array($form['permission'][$key]['#id']),
  146. FPA_ATTR_MODULE => $row[FPA_ATTR_MODULE],
  147. FPA_ATTR_PERMISSION => array(),
  148. );
  149. // Save row number for current module.
  150. $module = $i;
  151. }
  152. else {
  153. // Permission row.
  154. $row['class'][] = 'fpa-permission-row';
  155. $permission_system_name = '';
  156. // Might be empty if no modules are displayed in Permissions Filter module.
  157. if (!empty($form['checkboxes'][$first_role_index])) {
  158. $permission_system_name = $form['checkboxes'][$first_role_index][$key]['#return_value'];
  159. }
  160. $label = $permission_col_template;
  161. $label['description']['#markup'] = drupal_render($form['permission'][$key]);
  162. // Permissions filter might cause no Roles to display.
  163. if (count(element_children($form['checkboxes'])) == 0) {
  164. unset($label['checkbox_cell']);
  165. }
  166. // Readable
  167. $row['data'][] = array(
  168. 'data' => drupal_render($label),
  169. 'class' => array('permission'),
  170. );
  171. foreach (element_children($form['checkboxes']) as $rid) {
  172. $form['checkboxes'][$rid][$key]['#title'] = $form['role_names'][$rid]['#markup'] . ': ' . $form['permission'][$key]['#markup'];
  173. $form['checkboxes'][$rid][$key]['#title_display'] = 'invisible';
  174. // Filter permissions strips role id class from checkbox. Used by Drupal core functionality.
  175. $form['checkboxes'][$rid][$key]['#attributes']['class'][] = 'rid-' . $rid;
  176. // Set authenticated role behavior class on page load.
  177. if ($rid == 2 && $form['checkboxes'][$rid][$key]['#checked'] === TRUE) {
  178. $row['class'][] = 'fpa-authenticated-role-behavior';
  179. }
  180. // For all roles that inherit permissions from 'authenticated user' role, add in dummy checkbox for authenticated role behavior.
  181. if ($rid > 2) {
  182. $form['checkboxes'][$rid][$key]['#suffix'] = $dummy_checkbox_output; // '#suffix' doesn't have wrapping HTML like '#field_suffix'.
  183. }
  184. // Add rid's to row attribute for checked status filter.
  185. if ($form['checkboxes'][$rid][$key]['#checked'] === TRUE) {
  186. $row[FPA_ATTR_CHECKED][] = $rid;
  187. }
  188. else {
  189. $row[FPA_ATTR_NOT_CHECKED][] = $rid;
  190. }
  191. $row['data'][] = array(
  192. 'data' => drupal_render($form['checkboxes'][$rid][$key]),
  193. 'class' => array(
  194. 'checkbox',
  195. ),
  196. 'title' => array(
  197. $form['role_names'][$rid]['#markup'],
  198. ),
  199. // For role filter
  200. FPA_ATTR_ROLE => array(
  201. $rid,
  202. ),
  203. );
  204. }
  205. if (!empty($rid)) {
  206. $row['title'] = array(
  207. $form['checkboxes'][$rid][$key]['#return_value'],
  208. );
  209. $row[FPA_ATTR_SYSTEM_NAME] = array(
  210. $form['checkboxes'][$rid][$key]['#return_value'],
  211. );
  212. }
  213. // Mark current row with escaped permission name.
  214. $row[FPA_ATTR_PERMISSION] = array(
  215. // Permission system name.
  216. 0 => $permission_system_name,
  217. // Readable description.
  218. 1 => strip_tags($form['permission'][$key]['#markup']),
  219. );
  220. // Mark current row with current module.
  221. $row[FPA_ATTR_MODULE] = $rows[$module][FPA_ATTR_MODULE];
  222. $row[FPA_ATTR_PERMISSION] = array_unique(array_map('drupal_html_class', $row[FPA_ATTR_PERMISSION]));
  223. // Add current permission to current module row.
  224. $rows[$module][FPA_ATTR_PERMISSION] = array_merge($rows[$module][FPA_ATTR_PERMISSION], $row[FPA_ATTR_PERMISSION]);
  225. $rows[$module][FPA_ATTR_CHECKED] = array_unique(array_merge($rows[$module][FPA_ATTR_CHECKED], $row[FPA_ATTR_CHECKED]));
  226. $rows[$module][FPA_ATTR_NOT_CHECKED] = array_unique(array_merge($rows[$module][FPA_ATTR_NOT_CHECKED], $row[FPA_ATTR_NOT_CHECKED]));
  227. $modules[$rows[$module][FPA_ATTR_MODULE][0]][FPA_ATTR_PERMISSION][] = $row[FPA_ATTR_PERMISSION];
  228. }
  229. $rows[$i++] = $row;
  230. }
  231. $reset_button = array(
  232. '#type' => 'html_tag',
  233. '#tag' => 'input',
  234. '#attributes' => array(
  235. 'type' => 'reset',
  236. 'class' => 'form-submit',
  237. 'value' => t('Reset changes'),
  238. ),
  239. );
  240. // If there is no submit button, don't add the reset button.
  241. if (count(element_children($form['actions'])) > 0) {
  242. // Have the reset button appear before the submit button.
  243. array_unshift($form['actions'], $reset_button);
  244. }
  245. $actions_output = drupal_render_children($form['actions']);
  246. $header = array();
  247. $header[] = array(
  248. 'data' => t('Permission') . $actions_output,
  249. );
  250. foreach (element_children($form['role_names']) as $rid) {
  251. $header[] = array(
  252. 'data' => drupal_render($form['role_names'][$rid]) . $nameless_checkbox_output,
  253. 'class' => array(
  254. 'checkbox',
  255. ),
  256. 'title' => array(
  257. $form['role_names'][$rid]['#markup'],
  258. ),
  259. FPA_ATTR_ROLE => array(
  260. $rid,
  261. ),
  262. );
  263. $user_roles[$rid] = $form['role_names'][$rid]['#markup'];
  264. }
  265. $table = array(
  266. 'header' => $header,
  267. 'rows' => $rows,
  268. );
  269. $output = _fpa_wrapper($table, $modules, $user_roles, $actions_output);
  270. $output .= drupal_render_children($form);
  271. return $output;
  272. }
  273. /**
  274. * Wraps table output in the FPA filter.
  275. */
  276. function _fpa_wrapper($permissions_table, $modules, $user_roles, $actions_output) {
  277. $same_page = trim(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_PATH), '/') == $_GET['q'];
  278. $render = array(
  279. '#type' => 'container',
  280. '#attributes' => array(
  281. 'class' => array(
  282. 'fpa-container',
  283. ),
  284. ),
  285. );
  286. $hiders = array(
  287. 'fpa-hide-descriptions' => array(
  288. 'hide' => t('Hide descriptions'),
  289. 'show' => t('Show descriptions'),
  290. ),
  291. 'fpa-hide-system-names' => array(
  292. 'hide' => t('Hide system names'),
  293. 'show' => t('Show system names'),
  294. ),
  295. );
  296. $render['#attributes']['class'][] = 'fpa-hide-system-names';
  297. $hide_container = array(
  298. '#type' => 'container',
  299. '#attributes' => array(
  300. 'class' => array(
  301. 'fpa-toggle-container',
  302. ),
  303. ),
  304. );
  305. foreach ($hiders as $hide_class => $labels) {
  306. $hide_container[$hide_class] = array(
  307. '#theme' => 'link',
  308. '#text' => '',
  309. '#path' => '',
  310. '#options' => array(
  311. 'attributes' => array_merge($labels, array(
  312. 'fpa-toggle-class' => $hide_class,
  313. )),
  314. 'html' => TRUE,
  315. 'fragment' => ' ',
  316. 'external' => TRUE, // Prevent base path from being added to link.
  317. ),
  318. );
  319. }
  320. $render['hide_container'] = $hide_container;
  321. $wrapper = array(
  322. '#type' => 'container',
  323. '#attributes' => array(
  324. 'class' => array(
  325. 'fpa-wrapper',
  326. ),
  327. ),
  328. );
  329. $render['wrapper'] = &$wrapper;
  330. /**
  331. * <style /> block template.
  332. */
  333. $style_template = array(
  334. '#type' => 'container',
  335. '#attributes' => array(
  336. 'class' => array(
  337. 'style-wrapper-class-name', // Override on specific block.
  338. ),
  339. ),
  340. );
  341. $style_template['style'] = array(
  342. '#type' => 'html_tag',
  343. '#tag' => 'style',
  344. '#attributes' => array(
  345. 'type' => array(
  346. 'text/css',
  347. ),
  348. ),
  349. '#value' => '', // #value needed for closing tag.
  350. );
  351. /**
  352. * <style /> block for role filtering.
  353. */
  354. $wrapper['role_styles'] = $style_template;
  355. $wrapper['role_styles']['#attributes']['class'][0] = 'fpa-role-styles';
  356. /**
  357. * <style /> block for permission filtering.
  358. */
  359. $wrapper['perm_styles'] = $style_template;
  360. $wrapper['perm_styles']['#attributes']['class'][0] = 'fpa-perm-styles';
  361. /**
  362. * Left section contains module list and form submission button.
  363. */
  364. $left_section = array(
  365. '#type' => 'container',
  366. '#attributes' => array(
  367. 'class' => array(
  368. 'fpa-left-section',
  369. ),
  370. ),
  371. );
  372. $wrapper['left_section'] = &$left_section;
  373. /**
  374. * Right section contains filter form and permissions table.
  375. */
  376. $right_section = array(
  377. '#type' => 'container',
  378. '#attributes' => array(
  379. 'class' => array(
  380. 'fpa-right-section',
  381. ),
  382. ),
  383. );
  384. $wrapper['right_section'] = &$right_section;
  385. $module_template = array(
  386. FPA_ATTR_MODULE => array(),
  387. FPA_ATTR_PERMISSION => array(),
  388. 'data' => array(
  389. '#type' => 'container',
  390. '#attributes' => array(),
  391. 'link' => array(
  392. '#type' => 'markup',
  393. '#markup' => '', // l($module['text'], 'admin/people/permissions', $options)
  394. ),
  395. 'counters' => array(),
  396. 'total' => array(
  397. '#type' => 'html_tag',
  398. '#tag' => 'span',
  399. '#attributes' => array(
  400. 'class' => array('fpa-perm-total'),
  401. 'fpa-total' => 0,
  402. ),
  403. '#value' => '', // #value needed for closing tag.
  404. ),
  405. ),
  406. );
  407. $counter_template = array(
  408. '#type' => 'html_tag',
  409. '#tag' => 'span',
  410. '#attributes' => array(
  411. 'class' => array('fpa-perm-counter'),
  412. FPA_ATTR_PERMISSION => array(), // Counters only count permissions match.
  413. ),
  414. '#value' => '', // #value required for closing tag.
  415. );
  416. $items = array();
  417. $all_modules = array(
  418. 'text' => t('All modules'),
  419. FPA_ATTR_MODULE => array(),
  420. FPA_ATTR_PERMISSION => array(),
  421. );
  422. array_unshift($modules, $all_modules);
  423. $all_modules_counters = array();
  424. foreach ($modules as $module) {
  425. $module_item = $module_template;
  426. $module_item[FPA_ATTR_MODULE] = $module[FPA_ATTR_MODULE];
  427. $module_item[FPA_ATTR_PERMISSION] = array_reduce(array_pad($module[FPA_ATTR_PERMISSION], 1, array()), 'array_merge', array());
  428. // Use link for accessibility and tabability.
  429. $options = array(
  430. 'fragment' => 'all',
  431. );
  432. if (!empty($module['title'])) {
  433. $options['fragment'] = 'module-' . $module['title'][0];
  434. $options['attributes']['title'] = $module['title'][0];
  435. }
  436. $module_item['data']['link']['#markup'] = l($module['text'], 'admin/people/permissions', $options);
  437. foreach ($module[FPA_ATTR_PERMISSION] as $module_perm) {
  438. $counter_item = $counter_template;
  439. $counter_item['#attributes'][FPA_ATTR_PERMISSION] = $module_perm;
  440. $all_modules_counters[] = $counter_item;
  441. $module_item['data']['counters'][] = $counter_item;
  442. }
  443. $module_item['data']['total']['#attributes']['fpa-total'] = count($module[FPA_ATTR_PERMISSION]);
  444. $items[] = $module_item;
  445. }
  446. $items[0]['data']['counters'] = $all_modules_counters;
  447. $items[0]['data']['total']['#attributes']['fpa-total'] = count($all_modules_counters);
  448. foreach ($items as &$item) {
  449. $item['data'] = drupal_render($item['data']);
  450. }
  451. $left_section['list'] = array(
  452. '#items' => $items,
  453. '#theme' => 'item_list',
  454. );
  455. $left_section['buttons'] = array(
  456. '#type' => 'markup',
  457. '#markup' => $actions_output,
  458. );
  459. $filter_form = array(
  460. '#type' => 'container',
  461. '#attributes' => array(
  462. 'class' => array(
  463. 'fpa-filter-form',
  464. ),
  465. ),
  466. );
  467. $clear_button = array(
  468. '#type' => 'html_tag',
  469. '#tag' => 'input',
  470. '#attributes' => array(
  471. 'type' => array(
  472. 'button',
  473. ),
  474. 'class' => array(
  475. 'fpa-clear-search',
  476. 'form-submit',
  477. ),
  478. 'value' => 'Clear filter',
  479. ),
  480. );
  481. $default_filter = '';
  482. if (!empty($_GET['fpa_perm'])) {
  483. $default_filter = $_GET['fpa_perm'];
  484. }
  485. if (!empty($_COOKIE['fpa_filter']) && $same_page) {
  486. $default_filter = $_COOKIE['fpa_filter'];
  487. }
  488. $filter_form['permission_module_filter'] = array(
  489. '#type' => 'textfield',
  490. '#title' => t('Filter:'),
  491. '#description' => t('<p>Enter in the format of "permission@module",</p><p>e.g. <em>admin@system</em> will show only permissions with the<br>text "admin" in modules with the text "system".</p><p>This will also match on system name of a permission.</p>'),
  492. '#size' => 25,
  493. '#field_suffix' => drupal_render($clear_button),
  494. '#attributes' => array(
  495. 'placeholder' => array(
  496. 'permission@module',
  497. ),
  498. 'autofocus' => 'autofocus',
  499. ),
  500. '#value' => $default_filter,
  501. );
  502. /*
  503. * Populate the permission filter styles.
  504. */
  505. $matches = array();
  506. preg_match('/^\s*([^@]*)@?(.*?)\s*$/i', $filter_form['permission_module_filter']['#value'], $matches);
  507. array_shift($matches); // Remove whole match item.
  508. $safe_matches = array_map('drupal_html_class', $matches);
  509. $module_match = !empty($_COOKIE['module_match']) ? $_COOKIE['module_match'] : '*=';
  510. $filters = array(
  511. drupal_strlen($safe_matches[0]) > 0 ? ('[' . FPA_ATTR_PERMISSION . '*="' . $safe_matches[0] . '"]') : '',
  512. drupal_strlen($safe_matches[1]) > 0 ? ('[' . FPA_ATTR_MODULE . $module_match . '"' . $safe_matches[1] . '"]') : '',
  513. );
  514. $filter_styles = array(
  515. '.fpa-table-wrapper tr[' . FPA_ATTR_MODULE . ']{display: none;}',
  516. '.fpa-table-wrapper tr[' . FPA_ATTR_MODULE . ']',
  517. $filters[0],
  518. $filters[1],
  519. '{display: table-row;}',
  520. '.fpa-perm-counter{display: none;}',
  521. '.fpa-perm-counter',
  522. $filters[0],
  523. '{display: inline;}',
  524. '.fpa-left-section li[' . FPA_ATTR_MODULE . ']',
  525. drupal_strlen($filters[1]) > 0 ? $filters[1] : '[' . FPA_ATTR_MODULE . '=""]',
  526. '{margin-right:-1px; background-color: white; border-right: solid 1px transparent;}',
  527. );
  528. $wrapper['perm_styles']['style']['#value'] = implode('', $filter_styles);
  529. $cookie_roles = (!empty($_COOKIE['fpa_roles']) && $same_page) ? json_decode($_COOKIE['fpa_roles']) : array();
  530. $options = array(
  531. '*' => t('--All Roles'),
  532. );
  533. if (!empty($user_roles)) {
  534. $options += $user_roles; // Preserves keys.
  535. }
  536. if (in_array('*', $cookie_roles)) {
  537. $cookie_roles = array('*');
  538. }
  539. $filter_form['role_filter'] = array(
  540. '#type' => 'select',
  541. '#title' => t('Roles:'),
  542. '#description' => t('Select which roles to display.<br>Ctrl+click to select multiple.'),
  543. '#size' => 5,
  544. '#options' => $options,
  545. '#attributes' => array(
  546. 'multiple' => 'multiple',
  547. 'autocomplete' => 'off', // Keep browser from populating this from 'cached' input.
  548. ),
  549. '#value' => count(array_intersect($cookie_roles, array_keys($options))) > 0 ? $cookie_roles : array('*'),
  550. );
  551. /*
  552. * Populate the roles styles.
  553. */
  554. if (!in_array('*', $filter_form['role_filter']['#value'])) {
  555. $role_styles = array(
  556. '.fpa-table-wrapper [' . FPA_ATTR_ROLE . '] {display: none;}',
  557. );
  558. foreach ($filter_form['role_filter']['#value'] as $value) {
  559. $role_styles[] = '.fpa-table-wrapper [' . FPA_ATTR_ROLE . '="' . $value . '"] {display: table-cell;}';
  560. }
  561. $role_styles[] = '.fpa-table-wrapper [' . FPA_ATTR_ROLE . '="' . end($filter_form['role_filter']['#value']) . '"] {border-right: 1px solid #bebfb9;}';
  562. $wrapper['role_styles']['style']['#value'] = implode('', $role_styles);
  563. }
  564. $checked_status = array(
  565. '#type' => 'checkboxes',
  566. '#title' => t('Display permissions that are:'),
  567. '#options' => array(
  568. FPA_ATTR_CHECKED => t('Checked'),
  569. FPA_ATTR_NOT_CHECKED => t('Not Checked'),
  570. ),
  571. '#attributes' => array(),
  572. '#title_display' => 'before',
  573. '#description' => t('Applies to all visible roles.<br />Unsaved changes are not counted.<br />Most effective when a single role is visible.<br />Empty module rows sometimes display when used with permission filter.'),
  574. );
  575. $checked_status_keys = array_keys($checked_status['#options']);
  576. $checked_status['#value'] = array_combine($checked_status_keys, $checked_status_keys);
  577. $filter_form['checked_status'] = form_process_checkboxes($checked_status);
  578. foreach (element_children($filter_form['checked_status']) as $key) {
  579. $filter_form['checked_status'][$key]['#checked'] = TRUE;
  580. }
  581. $right_section['filter_form'] = $filter_form;
  582. $table_wrapper = array(
  583. '#type' => 'container',
  584. '#attributes' => array(
  585. 'class' => array(
  586. 'fpa-table-wrapper',
  587. ),
  588. ),
  589. );
  590. $table_wrapper['table'] = array(
  591. '#theme' => 'table',
  592. '#header' => $permissions_table['header'],
  593. '#rows' => $permissions_table['rows'],
  594. '#attributes' => array(
  595. 'id' => 'permissions',
  596. ),
  597. );
  598. // Show after full table HTML is loaded. Reduces progressive table load reflow/repaint.
  599. $table_wrapper['show_table'] = array(
  600. '#type' => 'html_tag',
  601. '#tag' => 'style',
  602. '#attributes' => array(
  603. 'type' => array(
  604. 'text/css',
  605. ),
  606. ),
  607. '#value' => '#permissions {display: table;} .fpa-table-wrapper {background: none;}',
  608. );
  609. $table_wrapper['buttons'] = array(
  610. '#type' => 'markup',
  611. '#markup' => $actions_output,
  612. );
  613. $right_section['table_wrapper'] = $table_wrapper;
  614. return drupal_render($render);
  615. }