/** present the user with a dialog to modify the workshop that is connected to node $node_id
 *
 * this prepares a dialog for the user filled with existing data (if any), possibly allowing
 * the user to modify the content. If the flag $viewonly is TRUE, this routine should only
 * display the content rather than let the user edit it. If the flag $edit_again is TRUE,
 * the routine should use the data available in the $_POST array, otherwise it should read
 * the data from the database (or wherever the data comes from). The parameter $href is the
 * place where the form should be POST'ed.
 *
 * The dialog should be added to the $output object. Useful routines are:
 * <code>
 * $output->add_content($content): add $content to the content area
 * $output->add_message($message): add $message to the message area (feedback to the user)
 * $output->add_popup_bottom($message): make $message popup in the browser after loading the page (uses JS)
 * $output->add_popup_top($message): make $message popup in the browser before loading the page (uses JS)
 * </code>
 * 
 * @param object &$output collects the html output (if any)
 * @param int $area_id the area in which $node_id resides
 * @param int $node_id the node to which this module is connected
 * @param array $module the module record straight from the database
 * @param bool $viewonly if TRUE, editing is not allowed (but simply showing the content is allowed)
 * @param bool $edit_again if TRUE start with data from $_POST, else use data from database
 * @param string $href the action property of the HTML-form, the place where data will be POST'ed
 * @return bool TRUE on success + output stored via $output, FALSE otherwise
 */
function crew_show_edit(&$output, $area_id, $node_id, $module, $viewonly, $edit_again, $href)
{
    global $USER;
    $module_id = intval($module['module_id']);
    $dialogdef = crew_get_dialogdef($output, $viewonly, $module_id, $area_id, $node_id, $USER->user_id);
    if ($edit_again) {
        // retrieve and (again) validate the POSTed values
        dialog_validate($dialogdef);
        // no need to show messages; we did that alread in crew_save() below
    }
    $output->add_content('<h2>' . t('crew_content_header', 'm_crew') . '</h2>');
    $output->add_content(t('crew_content_explanation', 'm_crew'));
    // Manually construct the form because of embedded HTML-table
    $in_table = FALSE;
    $postponed = array();
    $oddeven = 'even';
    $output->add_content(html_form($href));
    foreach ($dialogdef as $name => $item) {
        // this always works because the last item is not an acl field
        if ($in_table && substr($name, 0, 3) != 'acl') {
            $output->add_content(html_table_close());
            $in_table = FALSE;
        }
        if (!$in_table && substr($name, 0, 3) == 'acl') {
            $output->add_content(html_table(array('class' => 'acl_form')));
            $in_table = TRUE;
        }
        if (substr($name, 0, 3) == 'acl') {
            $oddeven = $oddeven == 'even' ? 'odd' : 'even';
            $attributes = array('class' => $oddeven);
            $output->add_content('  ' . html_table_row($attributes));
            $output->add_content('    ' . html_table_cell($attributes, dialog_get_label($item)));
            $widget = dialog_get_widget($item);
            if (is_array($widget)) {
                $output->add_content('    ' . html_table_cell($attributes));
                // add every radio button on a separate line
                $postfix = $item['type'] == F_RADIO ? '<br>' : '';
                foreach ($widget as $widget_line) {
                    $output->add_content('      ' . $widget_line . $postfix);
                }
                $output->add_content('    ' . html_table_cell_close());
            } else {
                $output->add_content('    ' . html_table_cell($attributes, $widget));
            }
            $output->add_content('  ' . html_table_row_close());
        } else {
            if ($item['type'] == F_SUBMIT) {
                $postponed[$name] = $item;
            } else {
                $output->add_content('<p>');
                $output->add_content(dialog_get_label($item) . '<br>');
                $widget = dialog_get_widget($item);
                if (is_array($widget)) {
                    // add every radio button on a separate line
                    $postfix = $item['type'] == F_RADIO ? '<br>' : '';
                    foreach ($widget as $widget_line) {
                        $output->add_content($widget_line . $postfix);
                    }
                } else {
                    $output->add_content($widget);
                }
            }
        }
    }
    foreach ($postponed as $item) {
        $output->add_content(dialog_get_widget($item));
    }
    $output->add_content('<p>');
    $output->add_content(html_form_close());
    return TRUE;
}
/** display the contact form
 *
 * this displays the contact form. Every destination gets a
 * separate DIV just below the listbox, with the additional
 * information for that destination. If JavaScript is NOT
 * enabled, all DIVs are displayed, otherwise only the
 * currently selected destination is displayed and the
 * others are not. IOW: this form is still usable even
 * without JS enabled AND it is screenreader-friendly.
 *
 * If there is only a single destination, the listbox is
 * not defined in the dialogdef and hence not rendered at all:
 * there is no point in showing a list of options
 * if there is nothing to choose from. This means that the
 * necessary javascript is NOT added and also no DIVs are
 * shown. So: a clean, uncluttered form in case of a single
 * destination.
 *
 * @param object &$theme collects the (html) output
 * @param array mailpage configuration data in a (nested) array
 * @param array $dialogdef array that defines the input fields
 * @return void output writted to $theme
 */
function mailpage_show_form(&$theme, $config, $dialogdef)
{
    //
    // 1 -- maybe output a header and an introduction
    //
    $header = trim($config['header']);
    if (!empty($header)) {
        $theme->add_content(html_tag('h2', '', $header));
    }
    $introduction = trim($config['introduction']);
    if (!empty($introduction)) {
        $theme->add_content($introduction);
    }
    $href = was_node_url($theme->node_record);
    //
    // 2 -- Render the dialog (maybe including the additional DIVs)
    //
    $postponed = array();
    $theme->add_content(html_form($href));
    foreach ($dialogdef as $name => $item) {
        if ($item['type'] == F_SUBMIT || isset($item['hidden']) && $item['hidden']) {
            $postponed[$name] = $item;
        } else {
            $theme->add_content('<p>');
            $theme->add_content(dialog_get_label($item) . '<br>');
            $widget = dialog_get_widget($item);
            if (is_array($widget)) {
                // add every radio button on a separate line
                $postfix = $item['type'] == F_RADIO ? '<br>' : '';
                foreach ($widget as $widget_line) {
                    $theme->add_content($widget_line . $postfix);
                }
            } else {
                $theme->add_content($widget);
            }
        }
        if ($name == 'destination') {
            foreach ($item['options'] as $index => $option) {
                $theme->add_content(sprintf('<div class="%s" id="%s%d">%s: %s</div>', 'mailpage_destination_option', 'mailpage_destination_', $index, htmlspecialchars($option['option']), htmlspecialchars($option['title'])));
            }
            // This suppresses the DIVs that correspond to currently
            // not selected options in the listbox
            $js = "<script><!--\n" . "var sel=document.getElementById('mailpage_destination');\n" . "sel.onchange=function() {\n" . "  var div;\n" . "  for(var i=0; i<this.length; ++i) {\n" . "    div=document.getElementById('mailpage_destination_'+this.options[i].value);\n" . "    div.style.display=(this.options[i].selected)?'block':'none';\n" . "  }\n" . "}\n" . "sel.onchange();\n" . "--></script>\n";
            $theme->add_content($js);
        }
    }
    $theme->add_content('<p>');
    foreach ($postponed as $item) {
        $theme->add_content(dialog_get_widget($item));
    }
    $theme->add_content(html_form_close());
}
/** construct a generic form with a dialog
 *
 * this constructs an HTML form with a simple dialog where
 *
 *  - every label and every widget has its own line
 *    (enforced by a BR-tag)
 *  - label/widget-combinations are separated with a P-tag
 *  - buttons are stringed together on a single line (ie no trailing BR)
 *
 * This should be sufficient for many dialogs.
 * If the layout needs to be more complex a custom dialog can
 * always be constructed using functions {@link dialog_get_label()}
 * and {@link dialog_get_widget()}.
 *
 * @param string $href the target of the HTML form
 * @param array &$dialogdef the array which describes the complete dialog
 * @param string $method method to submit data to the server, either 'post' or 'get'
 * @param string|array $attributes holds the attributes to add to the form tag
 * @return array constructed HTML-form with dialog, one line per array element
 * @uses html_form()
 */
function dialog_quickform($href, &$dialogdef, $method = 'post', $attributes = '')
{
    $buttons_seen = FALSE;
    $a = array(0 => html_form($href, $method, $attributes));
    // result starts with opening a form tag
    foreach ($dialogdef as $item) {
        if (!isset($item['name'])) {
            // skip spurious item (possibly empty array)
            continue;
        }
        $label = dialog_get_label($item);
        if (!empty($label)) {
            $a[] = '<p>';
            $a[] = $label . '<br>';
        }
        $widget = dialog_get_widget($item);
        if (is_array($widget)) {
            // add every radio button on a separate line
            $postfix = $item['type'] == F_RADIO ? '<br>' : '';
            foreach ($widget as $widget_line) {
                $a[] = $widget_line . $postfix;
            }
        } else {
            // quick and dirty:
            // add a <p> before the first button in a dialog
            // add a <br> after every 1-line item except buttons
            // result: fields line up nicely and buttons are on a single row
            $postfix = '';
            if ($item['type'] == F_SUBMIT) {
                if (!$buttons_seen) {
                    $buttons_seen = TRUE;
                    $a[] = '<p>';
                }
            } elseif (!(isset($item['hidden']) && $item['hidden'])) {
                $postfix = '<br>';
            }
            $a[] = $widget . $postfix;
        }
    }
    $a[] = '<p>';
    $a[] = html_form_close();
    return $a;
}
 /** construct a form with a dialog in a table with 2 or 3 columns
  *
  * this constructs a 2- or 3-column table and fills it with data from
  * the dialogdef.
  *
  * The first column holds the labels for the widgets.
  * The second column holds the corresponding widget, e.g. a list box with roles.
  * The optional third column (depends on the flag $show_related) shows
  * related information. This is used to list group/capacities and roles
  * from related groups (ie. groups of which the user is a member).
  *
  * The table has headers for the columns: 'Realm','Role' and optional 'Related'.
  * Rows in the table can have alternating colours via the odd/even class.
  * This is done via the stylesheet.
  *
  * @param string $href the target of the HTML form
  * @param array &$dialogdef the array which describes the complete dialog
  * @return array constructed HTML-form with dialog, one line per array element
  * @todo bailing out on non-array is a crude way of error handling: this needs to be fixed
  */
 function dialog_tableform($href, &$dialogdef, $show_related = FALSE)
 {
     if (!is_array($dialogdef)) {
         logger('dialog_tableform(): weird: there is no valid dialogdef?');
         return array(t('error_retrieving_data', 'admin'));
     }
     // result starts with opening a form tag and a 2- or 3-column table
     $attributes = array('class' => 'header');
     $a = array(html_form($href), html_table(array('class' => 'acl_form')), '  ' . html_table_row($attributes), '    ' . html_table_head($attributes, t('acl_column_header_realm', 'admin')), '    ' . html_table_head($attributes, t('acl_column_header_role', 'admin')));
     if ($show_related) {
         $a[] = '    ' . html_table_head($attributes, t('acl_column_header_related', 'admin'));
     }
     $a[] = '  ' . html_table_row_close();
     $oddeven = 'even';
     $postponed = array();
     foreach ($dialogdef as $item) {
         if (!isset($item['name'])) {
             // skip spurious item (possibly empty array)
             continue;
         }
         if ($item['type'] == F_SUBMIT || isset($item['hidden']) && $item['hidden']) {
             // always postpone the buttons and hidden fields to the end
             $postponed[] = $item;
             continue;
         }
         $oddeven = $oddeven == 'even' ? 'odd' : 'even';
         $attributes = array('class' => $oddeven);
         $a[] = '  ' . html_table_row($attributes);
         //
         // column 1 - realm
         //
         if ($this->area_view_enabled) {
             if (isset($item['area_id'])) {
                 // site level or area level
                 $icon = $this->get_icon_area($item['area_id'], $item['area_is_open'], $item['area_offset']);
             } else {
                 // node level, show a blank icon to line things up
                 $icon = $this->output->skin->get_icon('blank');
             }
         } else {
             $icon = '';
         }
         $a[] = '    ' . html_table_cell($attributes, ltrim($icon . ' ' . dialog_get_label($item)));
         //
         // column 2 - role
         //
         $widget = dialog_get_widget($item);
         if (is_array($widget)) {
             $a[] = '    ' . html_table_cell($attributes);
             // add every radio button on a separate line
             $postfix = $item['type'] == F_RADIO ? '<br>' : '';
             foreach ($widget as $widget_line) {
                 $a[] = '      ' . $widget_line . $postfix;
             }
             $a[] = '    ' . html_table_cell_close();
         } else {
             $a[] = '    ' . html_table_cell($attributes, $widget);
         }
         //
         // column 3 (optional) - related items in a single comma delimited string
         //
         if ($show_related) {
             $related = isset($item['related']) && !empty($item['related']) ? $item['related'] : '';
             $cell_content = is_array($related) ? implode(',<br>', $related) : $related;
             $a[] = '    ' . html_table_cell($attributes, $cell_content);
         }
         $a[] = '  ' . html_table_row_close();
     }
     $a[] = html_table_close();
     // now handle the postponed fields such as the Save and Cancel buttons and the hidden fields
     if (sizeof($postponed) > 0) {
         foreach ($postponed as $item) {
             $a[] = dialog_get_widget($item);
         }
     }
     $a[] = html_form_close();
     return $a;
 }