/**
 * Retrieve the html for a block of attributes.
 * @param array $attributes Array of attributes as returned from a call to data_entry_helper::getAttributes.
 * @param array $args Form argument array.
 * @param array $ctrlOptions Array of default options to apply to every attribute control.
 * @param array $outerFilter Name of the outer block to get controls for. Leave null for all outer blocks.
 * @param array $attrSpecificOptions Associative array of control names that have non-default options. Each entry
 * is keyed by the control name and has an array of the options and values to override.
 * @param array $idPrefix Optional prefix to give to IDs (e.g. for fieldsets) to allow you to ensure they remain unique.
 */
function get_attribute_html(&$attributes, $args, $ctrlOptions, $outerFilter = null, $attrSpecificOptions = null, $idPrefix = '', $helperClass = 'data_entry_helper')
{
    $lastOuterBlock = '';
    $lastInnerBlock = '';
    $r = '';
    foreach ($attributes as &$attribute) {
        if (in_array($attribute['id'], data_entry_helper::$handled_attributes)) {
            $attribute['handled'] = 1;
        }
        // Apply filter to only output 1 block at a time. Also hide controls that have already been handled.
        if (($outerFilter === null || strcasecmp($outerFilter, $attribute['outer_structure_block']) == 0) && !isset($attribute['handled'])) {
            if (empty($outerFilter) && $lastOuterBlock != $attribute['outer_structure_block']) {
                if (!empty($lastInnerBlock)) {
                    $r .= '</fieldset>';
                }
                if (!empty($lastOuterBlock)) {
                    $r .= '</fieldset>';
                }
                if (!empty($attribute['outer_structure_block'])) {
                    $r .= '<fieldset id="' . get_fieldset_id($attribute['outer_structure_block'], $idPrefix) . '"><legend>' . lang::get($attribute['outer_structure_block']) . '</legend>';
                }
                if (!empty($attribute['inner_structure_block'])) {
                    $r .= '<fieldset id="' . get_fieldset_id($attribute['outer_structure_block'], $attribute['inner_structure_block'], $idPrefix) . '"><legend>' . lang::get($attribute['inner_structure_block']) . '</legend>';
                }
            } elseif ($lastInnerBlock != $attribute['inner_structure_block']) {
                if (!empty($lastInnerBlock)) {
                    $r .= '</fieldset>';
                }
                if (!empty($attribute['inner_structure_block'])) {
                    $r .= '<fieldset id="' . get_fieldset_id($lastOuterBlock, $attribute['inner_structure_block'], $idPrefix) . '"><legend>' . lang::get($attribute['inner_structure_block']) . '</legend>';
                }
            }
            $lastInnerBlock = $attribute['inner_structure_block'];
            $lastOuterBlock = $attribute['outer_structure_block'];
            $options = $ctrlOptions + get_attr_validation($attribute, $args);
            // when getting the options, only use the first 2 parts of the fieldname as any further imply an existing record ID so would differ.
            $fieldNameParts = explode(':', $attribute['fieldname']);
            if (preg_match('/[a-z][a-z][a-z]Attr/', $fieldNameParts[count($fieldNameParts) - 2])) {
                $optionFieldName = $fieldNameParts[count($fieldNameParts) - 2] . ':' . $fieldNameParts[count($fieldNameParts) - 1];
            } elseif (preg_match('/[a-za-za-z]Attr/', $fieldNameParts[count($fieldNameParts) - 3])) {
                $optionFieldName = $fieldNameParts[count($fieldNameParts) - 3] . ':' . $fieldNameParts[count($fieldNameParts) - 2];
            } else {
                throw new exception('Option fieldname not found');
            }
            if (isset($attrSpecificOptions[$optionFieldName])) {
                $options = array_merge($options, $attrSpecificOptions[$optionFieldName]);
            }
            $r .= call_user_func($helperClass . '::outputAttribute', $attribute, $options);
            $attribute['handled'] = true;
        }
    }
    if (!empty($lastInnerBlock)) {
        $r .= '</fieldset>';
    }
    if (!empty($lastOuterBlock) && strcasecmp($outerFilter, $lastOuterBlock) !== 0) {
        $r .= '</fieldset>';
    }
    return $r;
}
/**
 * List of methods that can be used for a prebuilt form control generation.
 * @package Client
 * @subpackage PrebuiltForms.
 * @param array $attributes
 * @param array $args
 * @param array $defAttrOptions
 * @param array $outerFilter
 * @param array $blockOptions Associative array of control names that have non-default options. Each entry
 * is keyed by the control name and has an array of the options and values to override.
 * @param array $idPrefix Optional prefix to give to IDs (e.g. for fieldsets) to allow you to ensure they remain unique.
 */
function get_attribute_html($attributes, $args, $defAttrOptions, $outerFilter = null, $blockOptions = null, $idPrefix = '')
{
    $lastOuterBlock = '';
    $lastInnerBlock = '';
    $r = '';
    foreach ($attributes as $attribute) {
        // Apply filter to only output 1 block at a time. Also hide controls that have already been handled.
        if (($outerFilter === null || strcasecmp($outerFilter, $attribute['outer_structure_block']) == 0) && !isset($attribute['handled'])) {
            if (empty($outerFilter) && $lastOuterBlock != $attribute['outer_structure_block']) {
                if (!empty($lastInnerBlock)) {
                    $r .= '</fieldset>';
                }
                if (!empty($lastOuterBlock)) {
                    $r .= '</fieldset>';
                }
                if (!empty($attribute['outer_structure_block'])) {
                    $r .= '<fieldset id="' . get_fieldset_id($attribute['outer_structure_block'], $idPrefix) . '"><legend>' . lang::get($attribute['outer_structure_block']) . '</legend>';
                }
                if (!empty($attribute['inner_structure_block'])) {
                    $r .= '<fieldset id="' . get_fieldset_id($attribute['outer_structure_block'], $attribute['inner_structure_block'], $idPrefix) . '"><legend>' . lang::get($attribute['inner_structure_block']) . '</legend>';
                }
            } elseif ($lastInnerBlock != $attribute['inner_structure_block']) {
                if (!empty($lastInnerBlock)) {
                    $r .= '</fieldset>';
                }
                if (!empty($attribute['inner_structure_block'])) {
                    $r .= '<fieldset id="' . get_fieldset_id($lastOuterBlock, $attribute['inner_structure_block'], $idPrefix) . '"><legend>' . lang::get($attribute['inner_structure_block']) . '</legend>';
                }
            }
            $lastInnerBlock = $attribute['inner_structure_block'];
            $lastOuterBlock = $attribute['outer_structure_block'];
            $options = $defAttrOptions + get_attr_validation($attribute, $args);
            if (isset($blockOptions[$attribute['fieldname']])) {
                $options = array_merge($options, $blockOptions[$attribute['fieldname']]);
            }
            $r .= data_entry_helper::outputAttribute($attribute, $options);
            $attribute['handled'] = true;
        }
    }
    if (!empty($lastInnerBlock)) {
        $r .= '</fieldset>';
    }
    if (!empty($lastOuterBlock) && strcasecmp($outerFilter, $lastOuterBlock) !== 0) {
        $r .= '</fieldset>';
    }
    return $r;
}
 /**
  * Implement the link_species_popups parameter. This hides any identified blocks and pops them up when a certain species is entered.
  */
 protected static function link_species_popups($args)
 {
     $r = '';
     if (isset($args['link_species_popups']) && !empty($args['link_species_popups'])) {
         data_entry_helper::add_resource('fancybox');
         $popups = helper_base::explode_lines($args['link_species_popups']);
         foreach ($popups as $popup) {
             $tokens = explode("|", $popup);
             if (count($tokens) == 2) {
                 $fieldset = get_fieldset_id($tokens[1]);
             } else {
                 if (count($tokens) == 3) {
                     $fieldset = get_fieldset_id($tokens[1], $tokens[2]);
                 } else {
                     throw new Exception('The link species popups form argument contains an invalid value');
                 }
             }
             // insert a save button into the fancyboxed fieldset, since the normal close X looks like it cancels changes
             data_entry_helper::$javascript .= "\$('#{$fieldset}').append('<input type=\"button\" value=\"" . lang::get('Close') . "\" onclick=\"\$.fancybox.close();\" ?>');\n";
             // create an empty link that we can fire to fancybox the popup fieldset
             $r .= "<a href=\"#{$fieldset}\" id=\"click-{$fieldset}\"></a>\n";
             // add a hidden div to the page so we can put the popup fieldset into it when not popped up
             data_entry_helper::$javascript .= "\$('#{$fieldset}').after('<div style=\"display:none;\" id=\"hide-{$fieldset}\"></div>');\n";
             // put the popup fieldset into the hidden div
             data_entry_helper::$javascript .= "\$('#hide-{$fieldset}').append(\$('#{$fieldset}'));\n";
             // capture new row events on the grid
             data_entry_helper::$javascript .= "hook_species_checklist_new_row.push(function(data) {\n  if (data.preferred_name=='{$tokens['0']}') {\n    \$('#click-{$fieldset}').fancybox({showCloseButton: false}).trigger('click');\n  }\n});\n";
         }
     }
     return $r;
 }