Ejemplo n.º 1
0
 /**
  * Renders a screen for setting permissions on approval points.
  *
  * @return tempcode		The UI
  */
 function second_screen()
 {
     require_code('form_templates');
     // See if we're redefining everything
     $redefining = array_key_exists('redefine_points', $_POST);
     // Grab all of the requested points
     $points = array_map('trim', explode("\n", trim(post_param('points'))));
     // Throw out whitespace
     $temp_points = array();
     foreach ($points as $p) {
         if (strlen(trim($p)) > 0) {
             $temp_points[] = trim($p);
         }
     }
     $points = $temp_points;
     unset($temp_points);
     // Clean them up a bit. We'll allow spaces, but no other punctuation.
     $clean_points = array();
     foreach ($points as $p) {
         $clean_points[] = implode(' ', array_map('strip_tags', explode(' ', $p)));
     }
     $points = $clean_points;
     unset($clean_points);
     // Find any points which are already defined
     $all_points = get_all_approval_points();
     // This will hold new points
     $clarify_points = array();
     // This will hold existing points we're redefining
     $redefine_points = array();
     // See if we need to define any
     foreach ($points as $p) {
         if (!in_array($p, $all_points)) {
             // Found an undefined point. We need more information.
             $clarify_points[] = $p;
         } elseif ($redefining) {
             $redefine_points[] = $p;
         }
     }
     // These will hold our form fields
     $fields = new ocp_tempcode();
     $hidden = new ocp_tempcode();
     // Pass through the previous screen's data
     foreach (array('points', 'is_default', 'name') as $n) {
         $hidden->attach(form_input_hidden($n, post_param($n, '')));
     }
     // We need a list of groups so that the user can choose those to give
     // permission to
     $usergroups = $GLOBALS['FORUM_DRIVER']->get_usergroup_list(true, true, false, NULL, NULL);
     // Add the form elements for each section
     if (count($clarify_points) > 0) {
         $fields->attach(do_template('FORM_SCREEN_FIELD_SPACER', array('TITLE' => do_lang('DEFINE_WORKFLOW_POINTS'), 'HELP' => do_lang_tempcode('DEFINE_WORKFLOW_POINTS_HELP', implode(', ', $clarify_points)))));
         $counter = 0;
         foreach ($clarify_points as $p) {
             // Add a code to reference these elements by later
             $hidden->attach(form_input_hidden('code_' . strval($counter), $p));
             // Now add a list of the groups to allow
             $content = array();
             foreach ($usergroups as $group_id => $group_name) {
                 $content[] = array($group_name, 'groups_' . strval($counter) . '[' . strval($group_id) . ']', false, '');
             }
             $fields->attach(form_input_various_ticks($content, do_lang('WORKFLOW_POINT_GROUPS_DESC', $p), NULL, do_lang('WORKFLOW_POINT_GROUPS', $p), true));
             $counter++;
         }
     }
     if (count($redefine_points) > 0) {
         $fields->attach(do_template('FORM_SCREEN_FIELD_SPACER', array('TITLE' => do_lang('REDEFINE_WORKFLOW_POINTS'), 'HELP' => do_lang('REDEFINE_WORKFLOW_POINTS_HELP'))));
         // These points already exist, so look them up
         $all_points = array_flip(get_all_approval_points());
         foreach ($redefine_points as $p) {
             // Add a code to reference these elements by later
             $hidden->attach(form_input_hidden('redef_' . strval($all_points[$p]), $p));
             // Now add a list of the groups to allow, defaulting to those which
             // already have permission
             $groups = get_groups_for_point($all_points[$p], false);
             $content = array();
             foreach ($usergroups as $group_id => $group_name) {
                 $content[] = array($group_name, 'redef_groups_' . strval($all_points[$p]) . '[' . strval($group_id) . ']', in_array($group_id, $groups), '');
             }
             $fields->attach(form_input_various_ticks($content, do_lang('WORKFLOW_POINT_GROUPS_DESC', $p), NULL, do_lang('WORKFLOW_POINT_GROUPS', $p), true));
         }
     }
     $self_url = get_self_url();
     return do_template('FORM_SCREEN', array('TITLE' => do_template('SCREEN_TITLE', array('TITLE' => do_lang('DEFINE_WORKFLOW_POINTS'), 'HELP_URL' => '')), 'FIELDS' => $fields, 'TEXT' => '', 'HIDDEN' => $hidden, 'URL' => is_object($self_url) ? $self_url->evaluate() : $self_url, 'SUBMIT_NAME' => do_lang_tempcode('PROCEED')));
 }
Ejemplo n.º 2
0
/**
 * Handler for workflow form submission.
 *
 * @return tempcode		Either an error page or a success message
 */
function workflow_update_handler()
{
    require_lang('workflows');
    require_code('database');
    $success_message = do_lang('APPROVAL_UNCHANGED');
    /////////////////////////////////////////
    // Grab everything we need from $_POST //
    /////////////////////////////////////////
    $workflow_id = post_param('workflow_id');
    $content_id = post_param('content_id');
    $workflow_notes = post_param('workflow_notes');
    // Find out which approvals have been given
    $approvals = array();
    foreach (get_requirements_for_workflow(post_param('workflow_id')) as $approval_id) {
        // We might not have a value for this point, since we may not have given a tick box for it
        if (array_key_exists('approval_' . strval($approval_id), $_POST)) {
            $approvals[$approval_id] = post_param_integer('approval_' . strval($approval_id));
        } elseif (array_key_exists('tick_on_form__approval_' . strval($approval_id), $_POST)) {
            $approvals[$approval_id] = post_param_integer('tick_on_form__approval_' . strval($approval_id));
        }
    }
    ////////////////////////
    // Get member details //
    ////////////////////////
    // Find out which groups/members to inform, starting with the
    // original submitter
    $send_to_members = array();
    if (array_key_exists('send_author', $_POST)) {
        if (post_param_integer('send_author') == 1) {
            $submitter = get_submitter_of_workflow_content($content_id);
            if (!is_null($submitter)) {
                $send_to_members[$submitter] = 1;
            }
        }
    }
    // Now get the groups
    $group_ids = array();
    // Only remember 1 copy of each group
    foreach (get_requirements_for_workflow($workflow_id) as $requirement) {
        foreach (get_groups_for_point($requirement) as $group) {
            if (!in_array($group, $group_ids)) {
                if (post_param_integer('send_' . strval($group), 0) == 1) {
                    $group_ids[] = $group;
                }
            }
        }
    }
    // From the groups we can get the members, and from there the emails
    foreach ($GLOBALS['FORUM_DRIVER']->member_group_query($group_ids) as $member) {
        $send_to_members[$member['id']] = 1;
    }
    ////////////////////////////////////////////
    // Now play with the database as required //
    ////////////////////////////////////////////
    // See which values need updating (ie. approvals have been given/withdrawn)
    $updated_approvals = array();
    $all_approval_statuses = array();
    // Grab each point's status from the database
    $old_values = $GLOBALS['SITE_DB']->query_select('workflow_content_status', array('workflow_approval_name', 'status_code'), array('workflow_content_id' => $content_id));
    $accounted_for_statuses = array();
    // Look for any differences we need to make
    foreach ($old_values as $old_value) {
        $noted = false;
        // Keep a note of each value for including in emails
        // Only compare against values which we've been given
        if (array_key_exists($old_value['workflow_approval_name'], $approvals)) {
            $accounted_for_statuses[] = $old_value['workflow_approval_name'];
            // See if the database entry is the same as the given status
            if ($old_value['status_code'] != $approvals[$old_value['workflow_approval_name']]) {
                // If not then see if we have permission to change it
                $members_with_permission = array();
                foreach ($GLOBALS['FORUM_DRIVER']->member_group_query(get_groups_for_point($old_value['workflow_approval_name'])) as $permitted) {
                    $members_with_permission[] = $permitted['id'];
                }
                if (in_array(get_member(), $members_with_permission)) {
                    // Remember that this needs to be changed
                    $updated_approvals[$old_value['workflow_approval_name']] = $approvals[$old_value['workflow_approval_name']];
                    // Make a note of this value in the array of all statuses
                    $all_approval_statuses[$old_value['workflow_approval_name']] = $approvals[$old_value['workflow_approval_name']];
                    $noted = true;
                }
            }
        }
        if (!$noted) {
            // If we're here then this status has either not been passed or
            // it does not need modifying. Either way we can grab a valid
            // status from the database.
            $all_approval_statuses[$old_value['workflow_approval_name']] = $old_value['status_code'];
        }
    }
    // Now add any unaccounted-for points to those which need updating
    $new_approvals = array();
    foreach (array_keys($approvals) as $a) {
        if (!in_array($a, $accounted_for_statuses)) {
            $updated_approvals[$a] = $approvals[$a];
            $new_approvals[] = $a;
        }
    }
    // Now we know which fields to update, let's do so
    foreach ($updated_approvals as $approval_id => $status_code) {
        $success_message = do_lang('APPROVAL_CHANGED_DESCRIPTION');
        if (in_array($approval_id, $new_approvals)) {
            $GLOBALS['SITE_DB']->query_insert('workflow_content_status', array('status_code' => $status_code, 'approved_by' => get_member(), 'workflow_content_id' => $content_id, 'workflow_approval_name' => $approval_id));
        } else {
            $GLOBALS['SITE_DB']->query_update('workflow_content_status', array('status_code' => $status_code, 'approved_by' => get_member()), array('workflow_content_id' => $content_id, 'workflow_approval_name' => $approval_id), '', 1, NULL, false, false);
        }
    }
    // Update the notes (this is done destructively, but is simplest)
    // We append a timestamped log of the action taken
    $notes_approved = array();
    $notes_disapproved = array();
    foreach ($updated_approvals as $approval_id => $status_code) {
        if ($status_code) {
            $notes_approved[] = $approval_id;
        } else {
            // Just because it's not approved, doesn't mean that it was unticked.
            // It may have just been added to the workflow.
            if (!in_array($approval_id, $new_approvals)) {
                $notes_disapproved[] = $approval_id;
            }
        }
    }
    if (count($notes_approved) + count($notes_disapproved) > 0) {
        $note_title = date('Y-m-d H:i') . ' ' . $GLOBALS['FORUM_DRIVER']->get_username(get_member());
        $workflow_notes = $workflow_notes . "\n\n" . $note_title . "\n" . str_repeat('-', strlen($note_title));
        $notes_approved = array_map('get_translated_text', $notes_approved);
        $notes_disapproved = array_map('get_translated_text', $notes_disapproved);
        if (count($notes_approved) > 0) {
            $workflow_notes .= "\n" . do_lang('WORKFLOW_APPROVED') . ': ' . implode(', ', $notes_approved);
        }
        if (count($notes_disapproved) > 0) {
            $workflow_notes .= "\n" . do_lang('WORKFLOW_DISAPPROVED') . ': ' . implode(', ', $notes_disapproved);
        }
    }
    $GLOBALS['SITE_DB']->query_update('workflow_content', array('notes' => $workflow_notes), array('id' => $content_id), '', 1);
    /////////////////////////////
    // See if we're going live //
    /////////////////////////////
    // Validation is stored, for the most part, in a 'validated' field
    // of the content's table. Those which store it elsewhere must
    // specify this via their content-meta-aware info.
    // Grab lookup data from the workflows database
    $content_details = $GLOBALS['SITE_DB']->query_select('workflow_content', array('source_type', 'source_id'), array('id' => $content_id), '', 1);
    if ($content_details == array()) {
        warn_exit(do_lang_tempcode('_MISSING_RESOURCE', 'workflow_content->' . strval($content_id)));
    }
    // Now use it to find this content's validation field
    $hooks = find_all_hooks('systems', 'content_meta_aware');
    $found = false;
    // Guilty until proven innocent again
    foreach (array_keys($hooks) as $hook) {
        // Skip if this is not the hook we're after
        if ($hook != $content_details[0]['source_type']) {
            continue;
        }
        // Otherwise load and instantiate the hook
        require_code('hooks/systems/content_meta_aware/' . filter_naughty_harsh($hook));
        $ob = object_factory('Hook_content_meta_aware_' . filter_naughty_harsh($hook), true);
        if (is_null($ob)) {
            continue;
        }
        // Bail out if the hook fails
        // Grab information about the hook
        $info = $ob->info();
        $content_table = $info['table'];
        $content_field = $info['id_field'];
        if (array_key_exists('validated_field', $info)) {
            $content_validated_field = $info['validated_field'];
        } else {
            // Fall back to 'validated' if nothing is specified
            $content_validated_field = 'validated';
        }
        if ($info['id_field_numeric']) {
            // If so then flag it with a shorter name, and use a different
            // name for the converted ID (ocPortal avoids dynamic typing)
            $numeric = true;
            $numeric_id = intval($content_details[0]['source_id']);
            // Errors arise from passing an object, but should be noticed by type checker
        } else {
            // Otherwise set the flag as false. We've already got a string.
            $numeric = false;
        }
    }
    // Now we have the details required to lookup this entry, wherever it
    // is. Let's get its current validation status and compare to what
    // the workflow would have it be
    if ($numeric) {
        $content_is_validated = $GLOBALS['SITE_DB']->query_select($content_table, array($content_validated_field), array($content_field => $numeric_id), '', 1);
    } else {
        $content_is_validated = $GLOBALS['SITE_DB']->query_select($content_table, array($content_validated_field), array($content_field => $content_details[0]['source_id']), '', 1);
    }
    // Make sure we've actually found something
    if ($content_is_validated == array()) {
        $source_id = $content_details[0]['source_id'];
        $validated_field = $source_id->content_validated_field;
        warn_exit(do_lang_tempcode('_MISSING_RESOURCE', $content_table . '->' . $content_field . '->' . $validated_field));
    }
    // In order for content to go live all points must be approved
    // See if all points have been approved. If so, none will have
    // status 0
    $all_points_approved = false;
    if ($GLOBALS['SITE_DB']->query_select('workflow_content_status', array('workflow_approval_name'), array('workflow_content_id' => $content_id, 'status_code' => 0)) == array()) {
        $all_points_approved = true;
    }
    // We need to act if the validation status is different to the total
    // completion of the workflow
    if (($content_is_validated[0][$content_validated_field] == 1) != $all_points_approved) {
        $success_message = $all_points_approved ? do_lang('APPROVAL_COMPLETE') : do_lang('APPROVAL_REVOKED');
        $GLOBALS['SITE_DB']->query_update($content_table, array($content_validated_field => $all_points_approved ? 1 : 0), array($content_field => $content_details[0]['source_id']), '', 1);
    }
    ///////////////////////////////////////////
    // Now inform members about this content //
    ///////////////////////////////////////////
    // Make a nicely formatted list of the statuses
    $status_list = '';
    foreach ($all_approval_statuses as $point => $status) {
        $status_list .= get_translated_text($point) . ': ';
        $status_list .= $status == 1 ? 'approved' : 'not approved';
        $status_list .= ', ';
    }
    // At last we can send the email
    require_code('notifications');
    if (count($send_to_members) > 0) {
        $success_message .= do_lang('APPROVAL_CHANGED_NOTIFICATIONS');
    }
    //require_code('developer_tools');
    //inspect($emails);
    $subject = do_lang('APPROVAL_EMAIL_SUBJECT', NULL, NULL, NULL, get_site_default_lang());
    $body = do_lang('APPROVAL_EMAIL_BODY', post_param('http_referer', ocp_srv('HTTP_REFERER')), $status_list, $workflow_notes, get_site_default_lang());
    dispatch_notification('workflow_step', NULL, $subject, $body, $send_to_members);
    // Finally return a success message
    $return_url = strip_tags(post_param('return_url'));
    return redirect_screen(new ocp_tempcode(), $return_url, $success_message);
}