View source
<?php
define("FIELD_ROLE_AUTHOR", -1);
function workflow_fields_help($section) {
switch ($section) {
case 'admin/modules#description':
return t('Add per-state CCK field settings to workflows. <em>Note: Requires both workflow.module and content.module</em>.');
}
}
function workflow_fields_perm() {
return array(
'bypass field restrictions',
);
}
function workflow_fields_form_alter(&$form, $form_state, $form_id) {
if (isset($form['type']) && @$form['type']['#value'] . '_node_form' == $form_id) {
_workflow_fields_node_form_alter($form, $form_state, $form_id);
}
elseif ('workflow_state_add_form' == $form_id) {
_workflow_fields_state_form_alter($form, $form_state, $form_id);
}
}
function _workflow_fields_state_form_alter(&$form, $form_state, $form_id) {
$wid = $form['wid']['#value'];
$sid = isset($form['sid']) ? $form['sid']['#value'] : 0;
$types = db_query("SELECT type FROM {workflow_type_map} WHERE wid=%d", $wid);
if (empty($types)) {
return;
}
if (WORKFLOW_CREATION == db_result(db_query("SELECT sysid FROM {workflow_states} WHERE sid=%d", $sid))) {
$form['sysid'] = array(
'#type' => 'value',
'#value' => WORKFLOW_CREATION,
);
$form['weight'] = array(
'#type' => 'value',
'#value' => WORKFLOW_CREATION_DEFAULT_WEIGHT,
);
$form['state'] = array(
'#type' => 'value',
'#value' => t('(creation)'),
);
}
$form['#submit'][] = 'workflow_fields_state_form_submit';
$form['fields'] = array(
'#theme' => 'workflow_fields_state',
'#tree' => TRUE,
'#types' => array(
'#type' => 'value',
'#value' => array(),
),
'#weight' => 98,
);
$rids = array(
FIELD_ROLE_AUTHOR => t('author'),
);
$result = db_query("SELECT r.rid, r.name FROM {role} r ORDER BY r.name");
while ($obj = db_fetch_object($result)) {
$rids[$obj->rid] = $obj->name;
}
$userrefs = array();
while ($values = db_fetch_array($types)) {
$type = $values['type'];
$content = content_types($type);
$form['fields']['#types']['#value'][] = $type;
$options = $rids;
foreach ($content['fields'] as $userref) {
if ($userref['type'] == 'userreference') {
$options[$userref['field_name']] = $userrefs[$userref['field_name']] = $userref['widget']['label'];
}
}
$fields = _workflow_fields_get_extra_fields($type) + $content['fields'];
foreach ($fields as $field) {
$permissions = db_fetch_array(db_query("SELECT visible_roles, editable_roles FROM {workflow_fields} WHERE sid = %d AND name = '%s' AND type = '%s'", intval($sid), $field['field_name'], $type));
if ($permissions === FALSE) {
$permissions = array(
'visible_roles' => FIELD_ROLE_AUTHOR,
'editable_roles' => FIELD_ROLE_AUTHOR,
);
}
$visible = explode(',', $permissions['visible_roles']);
$editable = explode(',', $permissions['editable_roles']);
$form['fields'][$type][$field['field_name']]['visible'] = array(
'#type' => 'checkboxes',
'#options' => $options,
'#default_value' => $visible,
);
$form['fields'][$type][$field['field_name']]['editable'] = array(
'#type' => 'checkboxes',
'#options' => $options,
'#default_value' => $editable,
);
$type_shortcuts = array();
$type_css = str_replace('_', '-', $type);
$field_name_css = str_replace('_', '-', $field['field_name']);
$group = $type_css . '-' . $field_name_css;
$type_shortcuts[$group]['all'] = array(
'title' => t('all'),
'href' => "javascript:Drupal.workflowFields.select('all', '{$group}');",
);
$type_shortcuts[$group]['none'] = array(
'title' => t('none'),
'href' => "javascript:Drupal.workflowFields.select('none', '{$group}');",
);
$type_shortcuts[$group]['toggle'] = array(
'title' => t('toggle'),
'href' => "javascript:Drupal.workflowFields.select('toggle', '{$group}');",
);
$visible_group = $group . '-visible';
$type_shortcuts[$group]['visible'] = array(
'title' => t('visible'),
'href' => "javascript:Drupal.workflowFields.select('toggle', '{$visible_group}');",
);
$editable_group = $group . '-editable';
$type_shortcuts[$group]['editable'] = array(
'title' => t('editable'),
'href' => "javascript:Drupal.workflowFields.select('toggle', '{$editable_group}');",
);
$form['fields'][$type][$field['field_name']]['shortcuts'] = array(
'#type' => 'value',
'#value' => $type_shortcuts,
'#theme' => 'workflow_fields_shortcuts',
'#render title' => false,
);
}
}
foreach (array(
'',
'visible',
'editable',
) as $group) {
$shortcuts[$group]['all'] = array(
'title' => $group ? t($group) : t('all'),
'href' => "javascript:Drupal.workflowFields.select('all', '{$group}');",
);
$shortcuts[$group]['none'] = array(
'title' => t('none'),
'href' => "javascript:Drupal.workflowFields.select('none', '{$group}');",
);
$shortcuts[$group]['toggle'] = array(
'title' => t('toggle'),
'href' => "javascript:Drupal.workflowFields.select('toggle', '{$group}');",
);
foreach ($rids as $rid => $rname) {
$shortcuts[$group][$rid] = array(
'title' => t('role: ') . $rname,
'href' => "javascript:Drupal.workflowFields.select('{$rid}', '{$group}');",
);
}
if ($userrefs) {
foreach ($userrefs as $ref => $refname) {
$ref_css = str_replace('_', '-', $ref);
$shortcuts[$group][$ref] = array(
'title' => t('user: ') . $refname,
'href' => "javascript:Drupal.workflowFields.select('{$ref_css}', '{$group}');",
);
}
}
}
$form['shortcuts'] = array(
'#type' => 'value',
'#value' => $shortcuts,
'#theme' => 'workflow_fields_shortcuts',
'#render title' => true,
'#weight' => 97,
);
$form['submit']['#weight'] = 99;
}
function workflow_fields_theme() {
return array(
'workflow_fields_state' => array(
'arguments' => array(
'form' => NULL,
),
),
'workflow_fields_shortcuts' => array(
'arguments' => array(
'form' => NULL,
),
),
);
}
function theme_workflow_fields_state($form) {
$header = array(
t('Content type'),
t('Field name'),
t('Visible'),
t('Editable'),
t('Select'),
);
$rows = array();
foreach ($form['#types']['#value'] as $type) {
$content = content_types($type);
$fields = _workflow_fields_get_extra_fields($type) + $content['fields'];
foreach ($fields as $field) {
$rows[] = array(
$content['name'] . '<br/>(' . $type . ')',
$field['widget']['label'] . '<br/>(' . $field['field_name'] . ')',
drupal_render($form[$type][$field['field_name']]['visible']),
drupal_render($form[$type][$field['field_name']]['editable']),
drupal_render($form[$type][$field['field_name']]['shortcuts']),
);
}
}
$output = theme('table', $header, $rows, array(
'class' => 'workflow-fields-table',
)) . '<p />';
return $output;
}
function theme_workflow_fields_shortcuts($form) {
drupal_add_js(drupal_get_path('module', 'workflow_fields') . '/workflow_fields.js');
$output = '<div class="form-item">';
if ($form['#render title']) {
$output .= '<label>' . t('Select: ') . '</label>';
}
foreach ($form['#value'] as $group) {
$links = array();
foreach ($group as $key => $link) {
$links[] = "<a href=\"{$link['href']}\">{$link['title']}</a>";
}
$output .= implode(', ', $links) . '<br />';
}
$output .= '</div>';
return $output;
}
function workflow_fields_state_form_submit($form, &$form_state) {
if (isset($form_state['values']['fields'])) {
if (!isset($form_state['values']['sid'])) {
$form_state['values']['sid'] = db_result(db_query("SELECT sid FROM {workflow_states} WHERE wid = %d AND state = '%s'", $form_state['values']['wid'], $form_state['values']['state']));
}
db_query("DELETE FROM {workflow_fields} WHERE sid = %d", intval($form_state['values']['sid']));
foreach ($form_state['values']['fields'] as $type => $fields) {
foreach ($fields as $name => $field) {
$visible = array_filter($field['visible']);
$editable = array_filter($field['editable']);
db_query("INSERT INTO {workflow_fields} (sid, name, type, visible_roles, editable_roles) VALUES(%d, '%s', '%s', '%s', '%s')", $form_state['values']['sid'], $name, $type, implode(',', $visible), implode(',', $editable));
}
}
}
}
function _workflow_fields_node_form_alter(&$form, $form_state, $form_id) {
$node = $form['#node'];
$sid = workflow_node_current_state($node);
if (!is_numeric($sid)) {
$sid = db_result(db_query("SELECT sid FROM {workflow_states} ws \n LEFT JOIN {workflow_type_map} wtm ON ws.wid = wtm.wid \n WHERE wtm.type = '%s' AND ws.sysid = %d", $node->type, WORKFLOW_CREATION));
}
$content = content_types($node->type);
$fields = _workflow_fields_get_extra_fields($node->type) + $content['fields'];
$form['sid'] = array(
'#type' => 'value',
'#value' => $sid,
);
list($visibles, $editables) = _workflow_fields_compute_permissions($sid, $node->type, $node, 'edit');
if ($visibles) {
foreach ($visibles as $field_name => $visible) {
if (!isset($fields[$field_name])) {
continue;
}
$editable = $editables[$field_name];
if ($editable && $visible) {
continue;
}
$field = $fields[$field_name];
if (!empty($field['path'])) {
$path = $field['path'];
if (!_workflow_fields_array_path_exists($form, $path)) {
$path = FALSE;
}
}
else {
$path = _workflow_fields_array_key_path($field_name, $form, array(
'#field_info',
));
}
if ($path === FALSE) {
continue;
}
$node =& $form['#node'];
if (!isset($node->content)) {
$node = node_build_content($node, FALSE, TRUE);
}
if (isset($field['process'])) {
call_user_func_array($field['process'], array(
&$form,
$field,
$path,
$visible,
$editable,
isset($field['process arguments']) ? (array) $field['process arguments'] : array(),
));
}
else {
_workflow_fields_process_field($form, $field, $path, $visible, $editable);
}
if (count($path) > 1) {
_workflow_fields_hide_empty_fieldsets($form[$path[0]]);
}
}
}
}
function _workflow_fields_hide_empty_fieldsets(&$parent) {
foreach (element_children($parent) as $child) {
$element =& $parent[$child];
if (isset($element['#type']) && (!isset($element['#access']) || $element['#access'])) {
return FALSE;
}
if (!_workflow_fields_hide_empty_fieldsets($element)) {
return FALSE;
}
}
if (isset($parent['#type']) && $parent['#type'] == 'fieldset') {
$parent['#access'] = FALSE;
}
return TRUE;
}
function _workflow_fields_process_field(&$form, $field, $path, $visible, $editable) {
$element =& _workflow_fields_array_path($form, $path);
$parent =& _workflow_fields_array_path($form, array_slice($path, 0, -1));
if ($visible) {
if (!isset($field['extra'])) {
$parent[$field['field_name'] . '_view'] = array(
'#type' => 'markup',
'#value' => content_view_field($field, $form['#node'], FALSE, TRUE),
'#weight' => isset($element['#weight']) ? $element['#weight'] : $form['#field_info'][$field['field_name']]['widget']['weight'],
);
}
else {
$node = $form['#node'];
if (_workflow_fields_array_path_exists($node->content, $path)) {
$view = _workflow_fields_array_path($node->content, $path);
$parent[$field['field_name'] . '_view'] = $view;
}
}
if (isset($parent['#type']) && $parent['#type'] == 'fieldset') {
$parent['#access'] = TRUE;
}
}
$element['#access'] = FALSE;
}
function workflow_fields_workflow_fields($type) {
$content = node_get_types('type', $type);
$fields = array();
if ($content->has_title) {
$fields['title'] = array(
'label' => $content->title_label,
);
}
if ($content->has_body) {
$fields['body'] = array(
'label' => $content->body_label,
'process' => '_workflow_fields_process_body',
);
}
if (module_exists('taxonomy')) {
$vocabularies = taxonomy_get_vocabularies($type);
if (!empty($vocabularies)) {
foreach ($vocabularies as $vid => $vocabulary) {
$fields['vid_' . $vid] = array(
'label' => $vocabulary->name,
'path' => $vocabulary->tags ? array(
'taxonomy',
'tags',
$vid,
) : array(
'taxonomy',
$vid,
),
);
}
}
}
return $fields;
}
function _workflow_fields_get_extra_fields($type, $reset = FALSE) {
static $fields = array();
if (!isset($fields[$type]) || $reset) {
$fields[$type] = module_invoke_all('workflow_fields', $type);
foreach ($fields[$type] as $key => $field) {
$fields[$type][$key]['field_name'] = $key;
$fields[$type][$key]['widget']['label'] = $field['label'];
$fields[$type][$key]['extra'] = TRUE;
}
drupal_alter('workflow_fields', $fields, $type);
}
return $fields[$type];
}
function _workflow_fields_process_body(&$form, $field, $path, $visible, $editable, $arguments) {
$form['body_field']['#access'] = FALSE;
if ($visible) {
$form['body'] = $form['#node']->content['body'];
$form['body']['#weight'] = $form['#content_extra_fields']['body_field']['weight'];
}
}
function workflow_fields_workflow_operations($mode, $wid, $sid = 0) {
switch ($mode) {
case 'workflow':
break;
case 'state':
if (WORKFLOW_CREATION == db_result(db_query("SELECT sysid FROM {workflow_states} WHERE wid = %d AND sid = %d", $wid, $sid))) {
return array(
'workflow_creation_edit' => array(
'title' => t('Edit'),
'href' => "admin/build/workflow/state/{$wid}/{$sid}",
),
);
}
break;
}
}
function workflow_fields_menu() {
$items['admin/settings/workflow_fields'] = array(
'title' => 'Workflow Fields settings',
'description' => 'Global settings for the behaviour of Workflow Fields.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'workflow_fields_settings',
),
'access arguments' => array(
'administer workflow',
),
);
return $items;
}
function workflow_fields_settings() {
$form['workflow_fields_edit_invisible_when_editing'] = array(
'#type' => 'checkbox',
'#title' => t('Edit fields marked as "not visible" but "editable" when editing.'),
'#default_value' => variable_get('workflow_fields_edit_invisible_when_editing', TRUE),
);
$form['workflow_fields_hide_read_only_when_editing'] = array(
'#type' => 'checkbox',
'#title' => t('Hide fields marked as "not editable" when editing.'),
'#default_value' => variable_get('workflow_fields_hide_read_only_when_editing', FALSE),
);
return system_settings_form($form);
}
function _workflow_fields_compute_groups($node = NULL) {
global $user;
$groups = array_keys($user->roles);
if (isset($node) && isset($node->uid)) {
if ($user->uid == $node->uid) {
$groups[] = FIELD_ROLE_AUTHOR;
}
$content = content_types($node->type);
foreach ($content['fields'] as $name => $field) {
if ($field['type'] == 'userreference' && isset($node->{$name})) {
foreach ($node->{$name} as $uid) {
if ($uid['uid'] === $user->uid) {
$groups[] = $name;
}
}
}
}
}
return $groups;
}
function _workflow_fields_compute_permissions($sid, $type, $node, $op) {
$visibles = array();
$editables = array();
$groups = _workflow_fields_compute_groups($node);
$result = db_query("SELECT name, visible_roles, editable_roles FROM {workflow_fields} WHERE sid = %d AND type = '%s'", $sid, $type);
global $user;
while ($row = db_fetch_array($result)) {
$visible_roles = explode(',', $row['visible_roles']);
$editable_roles = explode(',', $row['editable_roles']);
$visibles[$row['name']] = user_access('bypass field restrictions') || (bool) array_intersect($groups, $visible_roles);
$editables[$row['name']] = user_access('bypass field restrictions') || (bool) array_intersect($groups, $editable_roles);
if ($op == 'edit') {
if (variable_get('workflow_fields_hide_read_only_when_editing', FALSE) && !$editables[$row['name']]) {
$visibles[$row['name']] = FALSE;
}
if (variable_get('workflow_fields_edit_invisible_when_editing', TRUE) && $editables[$row['name']]) {
$visibles[$row['name']] = TRUE;
}
if (!$visibles[$row['name']]) {
$editables[$row['name']] = FALSE;
}
}
}
return array(
$visibles,
$editables,
);
}
function _workflow_fields_array_key_path($needle, $haystack, $forbidden = array(), $path = array()) {
foreach ($haystack as $key => $val) {
if (in_array($key, $forbidden)) {
continue;
}
if (is_array($val) && is_array($sub = _workflow_fields_array_key_path($needle, $val, $forbidden, array_merge($path, (array) $key)))) {
return $sub;
}
elseif ($key === $needle) {
return array_merge($path, (array) $key);
}
}
return FALSE;
}
function &_workflow_fields_array_path(&$array, $path) {
$offset =& $array;
if ($path) {
foreach ($path as $index) {
$offset =& $offset[$index];
}
}
return $offset;
}
function _workflow_fields_array_path_exists($array, $path) {
$offset =& $array;
if ($path) {
foreach ($path as $index) {
if (!array_key_exists($index, $offset)) {
return FALSE;
}
$offset =& $offset[$index];
}
}
return TRUE;
}
function workflow_fields_field_access($op, $field, $account = NULL, $node = NULL) {
if (!$node) {
return TRUE;
}
$node = node_load($node->nid);
$sid = workflow_node_current_state($node);
if (!$sid) {
return TRUE;
}
if (!is_numeric($sid)) {
$sid = db_result(db_query("SELECT sid FROM {workflow_states} ws \n LEFT JOIN {workflow_type_map} wtm ON ws.wid = wtm.wid \n WHERE wtm.type = '%s' AND ws.sysid = %d", $node->type, WORKFLOW_CREATION));
}
list($visibles, $editables) = _workflow_fields_compute_permissions($sid, $node->type, $node, $op);
if (!isset($visibles[$field['field_name']])) {
return TRUE;
}
return $op == 'view' ? $visibles[$field['field_name']] : $visibles[$field['field_name']] && $editables[$field['field_name']];
}