workflow_access.features.inc 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. <?php
  2. /**
  3. * Workflow_access records are a **faux-exportable** component.
  4. */
  5. /**
  6. * Helper to find the roles needs by an export.
  7. *
  8. * @return array
  9. * A workflow_name-indexed hash of non-default roles in workflow_access for
  10. * that workflow.
  11. */
  12. function _workflow_access_get_affected_roles() {
  13. $sql = <<<SQL
  14. SELECT DISTINCT
  15. w.name AS wname,
  16. r.name AS rname
  17. FROM {workflow_access} wa
  18. INNER JOIN {workflow_states} ws ON wa.sid = ws.sid
  19. INNER JOIN {workflows} w ON ws.wid = w.wid
  20. INNER JOIN {role} r ON wa.rid = r.rid
  21. SQL;
  22. $roles = array();
  23. foreach (db_query($sql) as $row) {
  24. $roles[$row->wname][$row->rname] = $row->rname;
  25. }
  26. return $roles;
  27. }
  28. /**
  29. * Implements hook_features_export_options().
  30. *
  31. * Provide a list of all workflows as selectable Feature components.
  32. *
  33. * We'll make all workflow access records related to the selected workflows
  34. * available for export.
  35. */
  36. function workflow_access_features_export_options() {
  37. $workflows = array();
  38. foreach (workflow_get_workflows() as $workflow) {
  39. $workflows[$workflow->name] = t('workflow access configuration for: ') . $workflow->name;
  40. }
  41. return $workflows;
  42. }
  43. /**
  44. * Implements hook_features_export().
  45. *
  46. * Inform Features about dependencies.
  47. */
  48. function workflow_access_features_export($data, &$export, $module_name = '') {
  49. $roles = _workflow_access_get_affected_roles();
  50. $export['dependencies']['workflow_access'] = 'workflow_access';
  51. $export['dependencies']['workflow'] = 'workflow';
  52. $pipe = array();
  53. foreach ($data as $component) {
  54. $export['features']['workflow_access'][$component] = $component;
  55. // Access configuration for a workflow needs that worfklow to exist.
  56. $pipe['workflow'][$component] = $component;
  57. // And it needs the roles to which rights are granted.
  58. foreach ($roles[$component] as $rname) {
  59. $pipe['user_role'][$rname] = $rname;
  60. }
  61. }
  62. return $pipe;
  63. }
  64. /**
  65. * Implements hook_features_export_render().
  66. *
  67. * Instruct Features which php code to generate, including the code-ified
  68. * workflow access records we want to export from db into code.
  69. */
  70. function workflow_access_features_export_render($module_name, $data, $export = NULL) {
  71. $code = array();
  72. $code[] = ' $workflows = array();';
  73. // For each selected workflow, fetch all related workflow access records
  74. // we want to put into code.
  75. foreach ($data as $workflow_name) {
  76. $workflow = workflow_get_workflows_by_name($workflow_name);
  77. if (!empty($workflow)) {
  78. $states = workflow_get_workflow_states_by_wid($workflow->wid);
  79. if (!empty($states)) {
  80. $code[] = "\n \$workflows['$workflow_name'] = array();";
  81. foreach ($states as $state) {
  82. $access_records = workflow_access_get_features_workflow_access_by_sid($state->sid);
  83. if (!empty($access_records)) {
  84. $state_name = $state->state;
  85. $code[] = " \$workflows['$workflow_name']['$state_name'] = array();";
  86. foreach ($access_records as $record) {
  87. $rname = $record->rname;
  88. unset($record->rname);
  89. $code[] = " \$workflows['$workflow_name']['$state_name']['$rname'] = " . features_var_export($record, ' ') . ';';
  90. }
  91. }
  92. }
  93. }
  94. }
  95. }
  96. $code[] = "\n return \$workflows;";
  97. $code = implode("\n", $code);
  98. return array('workflow_access_features_default_settings' => $code);
  99. }
  100. /**
  101. * Implements hook_features_rebuild().
  102. *
  103. * Instruct Features to insert our records (that were exported into code)
  104. * into the workflow_access table.
  105. */
  106. function workflow_access_features_rebuild($module) {
  107. $workflow_access_records = module_invoke($module, 'workflow_access_features_default_settings');
  108. // retrieve the workflow ids
  109. $wids = array();
  110. foreach ($workflow_access_records as $workflow_name => $state) {
  111. $workflow = workflow_get_workflows_by_name($workflow_name);
  112. $wids[$workflow_name] = $workflow->wid;
  113. }
  114. foreach ($wids as $workflow_name => $wid) {
  115. $states = workflow_get_workflow_states_by_wid($wid);
  116. foreach ($states as $state) {
  117. // Remove all workflow access records for states belonging to this
  118. // workflow. We don't want lingering entries - we only want the ones we're
  119. // about to insert.
  120. workflow_access_delete_workflow_access_by_sid($state->sid);
  121. }
  122. }
  123. // Insert our workflow access records. They look like
  124. // workflow_name[state_name][role_name] => array(grant_name => 0|1, ...)
  125. foreach ($workflow_access_records as $workflow_name => $states) {
  126. foreach ($states as $state_name => $records) {
  127. $state = workflow_get_workflow_states_by_wid_state($wids[$workflow_name], $state_name);
  128. if (is_array($state)) {
  129. $state = array_pop($state);
  130. }
  131. foreach ($records as $rname => $record) {
  132. $record['sid'] = (is_array($state)) ? $state[0]->sid : $state->sid;
  133. if ($rname == WORKFLOW_FEATURES_AUTHOR_NAME) {
  134. $record['rid'] = -1;
  135. }
  136. else {
  137. $role = user_role_load_by_name($rname);
  138. $record['rid'] = $role->rid;
  139. }
  140. workflow_access_insert_workflow_access_by_sid($record);
  141. }
  142. }
  143. }
  144. }
  145. /**
  146. * Implements hook_features_revert().
  147. */
  148. function workflow_access_features_revert($module) {
  149. workflow_access_features_rebuild($module);
  150. }
  151. /**
  152. * Get workflow_access object like below by state id.
  153. *
  154. * array(
  155. * 'rname' => 'authenticated user',
  156. * 'grant_view' => 1,
  157. * 'grant_update' => 0,
  158. * 'grant_delete' => 0,
  159. * );
  160. *
  161. * State id and workflow id are not returned because they are implicit for a
  162. * given sid.
  163. */
  164. function workflow_access_get_features_workflow_access_by_sid($sid) {
  165. // Get all workflow access rules for a sid, where wa.rid is either a valid role or -1,
  166. // stands for the author
  167. $sql = <<<SQL
  168. SELECT
  169. r.name as rname,
  170. wa.grant_view, wa.grant_update, wa.grant_delete
  171. FROM {workflow_access} wa
  172. LEFT JOIN {role} r ON wa.rid = r.rid
  173. WHERE
  174. wa.sid = :sid AND (wa.rid = r.rid OR wa.rid = -1)
  175. SQL;
  176. $results = db_query($sql, array(':sid' => $sid));
  177. $records = $results->fetchAll();
  178. foreach ($records as $record) {
  179. if (empty($record->rname)) {
  180. $record->rname = WORKFLOW_FEATURES_AUTHOR_NAME;
  181. }
  182. }
  183. return $records;
  184. }