<?php
defined( 'ABSPATH' ) or exit;   // show a blank page if try to access this file directly

require_once( EWZ_PLUGIN_DIR . 'classes/validation/ewz-item-list-input.php' );
require_once( EWZ_PLUGIN_DIR . 'classes/validation/ewz-item-list-IPP-input.php' );
require_once( EWZ_PLUGIN_DIR . 'classes/ewz-item-list.php' );
require_once( EWZ_PLUGIN_DIR . 'classes/ewz-field.php' );
require_once( EWZ_PLUGIN_DIR . 'classes/ewz-webform.php' );
require_once( EWZ_PLUGIN_DIR . 'classes/ewz-exception.php' );
require_once( EWZ_PLUGIN_DIR . 'includes/ewz-common.php' );
require_once( EWZ_CUSTOM_DIR . 'includes/ewz-admin.php' );
require_once( EWZ_CUSTOM_DIR . 'ewz-custom-data.php' );

/**
 * Set the items-per-page user option
 *
 * Called via ajax from item list page
 * @return string  blank or error message
 */
function ewz_set_ipp(){
    try{
        $input = new Ewz_Item_List_IPP_Input( $_POST );
        $requestdata  = $input->get_input_data();
    } catch( Exception $e ){
        return "Invalid input for items-per-page: " .$e->getMessage();
    }
    update_user_meta(
        get_current_user_id(),
        'ewz_itemsperpage',
        $requestdata['ewz_ipp'] );
    return '';
}


/**
 * Attach images to selected page
 *
 * Called via ajax from item list page
 * Generate new copies of the images in the regular uploads directory, so the page is not
 * in any way tied to entrywizard.
 *
 * @return string status message
 */
function ewz_check_and_attach_imgs()
{
    // validate the input
    try{
        $input = new Ewz_Item_List_Input( $_POST );
        $requestdata  = $input->get_input_data();
    } catch (Exception $e) {
        return $e->getMessage();
    }

    $webform = new Ewz_Webform( $requestdata['webform_id'] );
    if( !Ewz_Permission::can_manage_webform( $webform->webform_id, $webform->layout_id ) ) {
        throw new EWZ_Exception( 'Attempt to attach items without permission to manage webform' );
    }

    // save the options for attaching, because may need to use the same ones for several pages
    $save_prefs = array(
        'ewz_page_sel' => $requestdata['ewz_page_sel'],
        'img_comment'  => $requestdata['img_comment'],
        'img_size'     => $requestdata['img_size'],
        'ifield'       => $requestdata['ifield'],
        'dups_ok'      => $requestdata['dups_ok'],
        'img_qual'     => $requestdata['img_qual']
    );
    $webform->save_attach_prefs( $save_prefs );

    $count = 0;
    $n = 0;
    if( isset( $requestdata['ewz_check'] ) ){
        $n = count( $requestdata['ewz_check'] );
    }
    $errmsg = '';

    // allow extra time for processing - this can be slow
    $timelimit = ini_get('max_execution_time');
    if( 5 * $n > $timelimit ){
        set_time_limit ( 5 * $n );
    }

    if( isset( $requestdata['ewz_check'] ) ){
        $items = array();
        foreach ( $requestdata['ewz_check'] as $n=>$item_id ) {
            $items[$n] = new Ewz_Item((int)$item_id);
        }


        $rows = ewz_get_item_rows(
            $items,
            Ewz_Field::get_fields_for_layout( $webform->layout_id, 'ss_column' ) ,
            Ewz_Layout::get_extra_cols( $webform->layout_id ),
            $webform
        );        // has been html-escaped

        foreach( $items as $n=>$item ){
            $msg = ewz_attach_item( $item,  $requestdata, $rows[$n] );
            if( $msg ){
                $errmsg .= $msg;
            } else {
                ++$count;
            }
        }
    }
    $errmsg .= "  $count items attached";
    return $errmsg;
}

/**
 * Attach a single item to a page
 *
 *
 * @param  Ewz_Item          $item             item to be attached
 * @param  array<mixed>      $requestdata      parameters for attachment: destination page, image size, coments allowed
 * @param  array<string>           $row
 * @param  boolean           $note_attachment  if true, record the page title in the item data
 * @return string            error message or empty string
 */
function ewz_attach_item( $item, $requestdata, $row, $note_attachment=true ){
    $msg = '';
    $item_id = $item->item_id;
    try{
        if( !count( $item->item_files ) || !array_key_exists( $requestdata['ifield'], $item->item_files ) ){
            $msg .= "No image file for item with id $item_id.\n";
            return $msg;
        }
        if(  !$requestdata['dups_ok'] && isset( $item->item_data['attachedto'] ) &&
        ( strpos( $item->item_data['attachedto'], get_the_title( $requestdata['ewz_page_sel'] ) ) !== FALSE ) ){
            $msg .= "Item $item_id is already attached to " . $requestdata['ewz_page_sel'];
            return $msg;
        }

        foreach ( $item->item_files as $field_id => $file ) {
            if( ( $requestdata['ifield'] == $field_id ) ) {
                if( !isset( $file['fname'] ) ){
                    throw new EWZ_Exception( "No image file found" );
                }
                $orig_file = wp_check_filetype_and_ext( $file['fname'],  basename( $file['fname'] ) );
                $filename = ewz_create_attachment_file( $file['fname'], $requestdata['img_size'], $requestdata['img_qual'] );
                $attachment = array(
                    'post_mime_type' => $orig_file['type'],
                    'comment_status' => $requestdata['img_comment'] ? 'open' : 'closed',
                    'post_name'      => basename($filename),
                    'post_status'    => 'inherit',
                    'post_author'    => $item->user_id,
                );
                if( isset( $item->item_data[$field_id]['pexcerpt'] ) ){
                    $attachment['post_excerpt'] = $item->item_data[$field_id]['pexcerpt'];
                } elseif(isset($requestdata['bexcerpt'])) {
                    $attachment['post_excerpt'] = ewz_replace_array( $requestdata['bexcerpt'], $row );
                }
                if( isset( $item->item_data[$field_id]['pcontent'] ) ){
                    $attachment['post_content']  = $item->item_data[$field_id]['pcontent'];
                } elseif(isset($requestdata['bcontent'])) {
                    $attachment['post_content'] = ewz_replace_array( $requestdata['bcontent'], $row );
                }
                if( isset( $item->item_data[$field_id]['ptitle'] ) ){
                    $attachment['post_title'] = $item->item_data[$field_id]['ptitle'];
                } elseif(isset($requestdata['btitle'])) {
                    $attachment['post_title'] = ewz_replace_array( $requestdata['btitle'], $row );
                }
                if( isset( $item->item_data[$field_id]['tag'] ) ){
                    $attachment['post_tag'] = $item->item_data[$field_id]['ptag'];
                }

                // insert an attachment into the media library
                $attach_id = wp_insert_attachment( $attachment, $filename, $requestdata['ewz_page_sel'] );
                if( !$attach_id ){
                    throw new EWZ_Exception("Failed to create attachment file");
                }
                // must first include the image.php file for the function wp_generate_attachment_metadata() to work
                require_once(ABSPATH . 'wp-admin/includes/image.php');

                // This function generates metadata for an image attachment. It also creates a thumbnail and other intermediate
                // sizes of the image attachment based on the sizes defined on the Settings_Media_Screen.
                $attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
                wp_update_attachment_metadata( $attach_id, $attach_data );

                // if note_attachment ( may not always have permission to do this ),
                // in $item, save the fact that the attachment was done
                if( $note_attachment ){
                    $item->record_attachment( $requestdata['ewz_page_sel'] );
                    $item->save();
                }
            }
        }
    } catch( Exception $e ) {
        $msg .= "\nItem $item_id: " . $e->getMessage();
    }
    return $msg;
}

/**
 * @param  string $string
 * @param  array<mixed>  $data
 * @return string
 */
function ewz_replace_array( $string, $data ){
    $matches = array();
    preg_match_all( '/\[~(.*?)\]/', $string, $matches );
    foreach( $matches[1] as $n => $ident ){
        $string = str_replace( "[~{$ident}]", $data[$ident], $string );
    }
    return $string;
}


/**
 * Create a (possibly resized) copy of an uploaded image
 *
 * To avoid problems with deletion when an image is attached to another page, create a (possibly resized) copy
 *
 * @param  string  $fpath        path to uploaded image
 * @param  string  $size_string  size of copy to be created
 * @param  string  $qual
 *              ( must be 'full' or one of the size names set in wordpress, either in settings/media or via the theme )
 * @return string  path to the newly created copy
 */
function ewz_create_attachment_file( $fpath, $size_string, $qual ){
    $iqual = (int)$qual;

    $upload_dir = wp_upload_dir();

    $base = basename( $fpath );

    $attach_path =  $upload_dir['path'] . '/' . wp_unique_filename( $upload_dir['path'], $base );

    $image = wp_get_image_editor( $fpath );
    if( is_wp_error( $image ) ){
        throw new EWZ_Exception( "Failed to copy image $base\n" );
    }
    if( $iqual > -1 ){
        $image->set_quality($iqual);
    }
    if( $size_string != 'full' ){
        $max_width  = intval( get_option( "{$size_string}_size_w" ) );
        $max_height = intval( get_option( "{$size_string}_size_h" ) );
        $image->resize( $max_width, $max_height, false );
    }
    $status = $image->save( $attach_path );
    if( is_wp_error( $status ) ){
        throw new EWZ_Exception( "Error creating attachment file $fpath : " . $status->get_error_message() );
    }

    return $attach_path;
}


/**
 * Batch delete selected items
 * @param  boolean  $deleteFiles
 * @return string  status message
 */
function ewz_batch_delete_items( $deleteFiles )
{

    $data = array_merge( $_POST, $_GET );
    if ( !( isset( $data['webform_id'] ) &&
    Ewz_Permission::can_manage_webform( $data['webform_id'], 0 ) ) ){
        throw new EWZ_Exception( 'Insufficient Permissions To Modify Data' );
    }
    try{
        $input = new Ewz_Item_List_Input( $data );
        $requestdata  = $input->get_input_data();
    } catch( Exception $e ){
        return $e->getMessage();
    }
    $items_for_deletion = array();
    if( isset( $requestdata['ewz_check'] ) ){
        $items_for_deletion = $requestdata['ewz_check'];
    }
    $n = 0;
    $msgs = '';
    foreach ( $items_for_deletion as $item_id ) {
        $item = new Ewz_Item( $item_id );
        // item should belong to input webform
        if( $item->webform_id == $data['webform_id'] ){
            try{
                $msgs .= "\n" . $item->delete( $deleteFiles );
            } catch( Exception $e ){
                $msgs .= "\n$item_id ERROR: " . $e->getMessage();
            }
            ++$n;
        } else {
            throw new EWZ_Exception( 'Attempt to delete item on different webform' );
        }
    }
    return "$n items deleted. ". $msgs;
}


/**
 * Get the header array for the item-list page
 *
 * @param   array<mixed> $fields of EWZ_Fields
 * @param   array<int> $extra_cols  of extra columns for display
 * @return  array<string> - headers for the item list page
 */
function ewz_get_headers( $fields, $extra_cols )
{
    $headers = array();
    $img_data = array( 'ss_col_w' => 'Width', 'ss_col_h' => 'Height', 'ss_col_o' => 'Orientation' );
    foreach ( $fields as $field ) {
        if ( $field->ss_column >= 0 ) {
            $headers[$field->ss_column + 1] = $field->field_ident;
        }
        if ( 'img' == $field->field_type ) {
            // add in the width, height and orientation data
            foreach ( $img_data as $ss_img_col => $ss_img_header ) {
                $ssimgcol = $field->fdata[$ss_img_col];
                if ( $ssimgcol >= 0 ) {
                    $headers[$ssimgcol + 1] = $ss_img_header;
                }
            }
        }
        if ( 'str' == $field->field_type ) {
            // add in the "formatted text" column
            $sstxtcol = isset( $field->fdata['ss_col_fmt'] ) ? $field->fdata['ss_col_fmt'] : -1;
            if ( $sstxtcol >= 0 ) {
                $headers[$sstxtcol + 1] = 'Formatted ' . $field->field_ident;
            }
        }
    }

    $dheads = Ewz_Layout::get_all_display_headers();

    foreach ( $extra_cols as $xcol => $sscol ) {
        if ( $sscol >= 0 ) {
            $ssc = $sscol + 1;
            if( isset( $dheads[$xcol] ) ){
                $headers[$ssc] = $dheads[$xcol]['header'];
            }
        }
    }

    ksort( $headers, SORT_NUMERIC );
    return $headers;
}
/**
 * Get the header array for the edit view of the item-list page
 *     -- only show values that were set by user
 * @param  array<Ewz_Field> $fields  of EWZ_Fields
 * @return array<string> - headers for the item list page
 */
function ewz_get_headers_for_edit( $fields )
{
    $headers = array();
    foreach ( $fields as $field ) {
        if ( $field->ss_column >= 0 ) {
            $headers[$field->ss_column + 1] = $field->field_ident;
        }
    }

    ksort( $headers, SORT_NUMERIC );
    return $headers;
}

/**
 * Return the list of columns that contain images
 *
 * @param   array<Ewz_Field> $fields   of EWZ_Fields
 * @return  array<string> of field identifiers representing columns that contain images
 */
function ewz_get_img_cols( $fields )
{

    $image_columns = array();
    foreach ( $fields as $field ) {
        if ( 'img' == $field->field_type  ) {
            $image_columns[$field->field_id] = $field->field_ident;
        }
    }
    return $image_columns;
}

/**
 * Generate the array of rows for the 'edit' view of the item list table
 * This is a simplified version of ewz_get_item_rows, concerned only with
 * data actually uploaded by the user using Ewz_Fields.
 * Additionally, it generates a hidden input field of user_id.
 * NB: Because it contains html, needs to be cleaned up and escaped
 *
 * @param array<Ewz_Item>        $items  of Ewz_Items, indexed on item_id
 * @param array<Ewz_Field>        $fields of Ewz_Fields, indexed on field_id
 * @param Ewz_Webform  $wform
 * @param array<int>        $items_for_edit   of id's of items to be edited
 *
 * @return array<mixed>  of strings containing the html content of the item table
 *
 */
function ewz_get_item_rows_for_edit( $items, $fields, $wform, $items_for_edit )
{
    $maxcol = max( array_map( function($v){ return $v->ss_column; },  $fields ) );

    // Need to do any html-escaping here, because image columns may legitimately include html
    $n = 0;
    $rows = array( );
    foreach ( $items as $item ) {
        if( $items_for_edit && in_array( $item->item_id, $items_for_edit ) ){
            $rows[$n] = array_fill( 0, $maxcol + 1, '' );
            $rows[$n][0] = $item->item_id;

            // image columns from item_files
            if ( $item->item_files ) {
                foreach ( $item->item_files as $field_id => $item_file ) {
                    $field = $fields[$field_id];
                    if( isset( $item_file['fname'] ) && $item_file['fname'] ){
                        if ( array_key_exists( $field_id, $fields ) && $fields[$field_id]->ss_column >= 0 ) {
                            $col = $fields[$field_id]->ss_column + 1;
                            $basename = basename( $item_file['fname'] );
                            $uploads = wp_upload_dir();
                            $clickFunc = 'show_full("' . ewz_file_to_url( "{$uploads['basedir']}/ewz_img_uploads/{$wform->webform_ident}/$basename" ) . '");';

                            $rows[$n][$col] =
                                '<a onClick="' . esc_attr( $clickFunc ) . '">' .
                                '<img  src="' . esc_attr( $item_file['thumb_url'] ) . '">' .
                                '</a><br>' . $basename;

                            $rows[$n][$col] .= '<input type="hidden" name="user_id" value="' .  esc_attr("$item->user_id") . '">';
                        }
                    }
                }
            }
            // other columns from item_data only, no extra columns or calculated ones
            foreach ( $fields as $field_id => $field ) {
                if( isset( $item->item_data[$field_id] ) ){
                    $field_value_arr = $item->item_data[$field_id];
                } else {
                    $field_value_arr = array('value'=>'');
                }
                $field = new Ewz_Field( $field_id );
                if ( $fields[$field_id]->ss_column >= 0 ) {
                    $col = $fields[$field_id]->ss_column + 1;
                    if ( $field->field_type != 'img' ) {
                        // image columns have already been set
                        // assert(  !isset( $rows[$n][$col] ) ||  !$rows[$n][$col] );
                        $rows[$n][$col]= ewz_display_webform_field( $n, $wform->webform_id, $field_value_arr['value'], $field, false );
                    }
                }
            }
        }
        ksort( $rows[$n], SORT_NUMERIC );
        ++$n;
    }
    return $rows;
}

/**
 * Generate the array of rows for the item list table
 *
 * @param array<Ewz_Item> $items        of Ewz_Items, indexed on item_id
 * @param array<Ewz_Field> $fields       of Ewz_Fields, indexed on field_id
 * @param array<int> $extra_cols   of integers representing column numbers, indexed
 *                        by the extra_column abbreviations
 *                       ('att','aat','aae','aac','add','dlc','dtu','iid','wft','wid','wfm','nam','fnm',
 *                        'lnm', 'mnm', 'mem','mid', 'mli', 'custom1', 'custom2', ... )
 * @param Ewz_Webform   $wform
 *
 * @return array<mixed> of strings containing the html content of the item table
 *
 * NB: Because it contains html, needs to be cleaned up and escaped
 */
function ewz_get_item_rows( $items, $fields, $extra_cols, $wform )
{
    $maxcol = max( array_map( function($v){ return $v->ss_column; },  $fields ) );
    if( count( array_values( $extra_cols ) ) > 0 ){
        $maxcol = max( $maxcol, max( array_values( $extra_cols ) ) );
    }

    // Need to do any html-escaping here, because image columns may legitimately include html
    $n = 0;
    $rows = array( );
    foreach ( $items as $item ) {
        $rows[$n] = array_fill( 0, $maxcol + 1, '' );
        $rows[$n][0] = $item->item_id;

        // image columns from item_files
        if ( $item->item_files ) {
            foreach ( $item->item_files as $field_id => $item_file ) {
                $field = $fields[$field_id];
                if( isset( $item_file['fname'] ) && $item_file['fname'] ){
                    if ( array_key_exists( $field_id, $fields ) && $fields[$field_id]->ss_column >= 0 ) {
                        $col = $fields[$field_id]->ss_column + 1;
                        $basename = basename( $item_file['fname'] );
                        $uploads = wp_upload_dir();
                        $clickFunc = 'show_full("' . ewz_file_to_url( "{$uploads['basedir']}/ewz_img_uploads/{$wform->webform_ident}/$basename" ) . '");';

                        $rows[$n][$col] =
                            '<a onClick="' . esc_attr( $clickFunc ) . '">' .
                            '<img  src="' . esc_attr( $item_file['thumb_url'] ) . '">' .
                            '</a><br>' . $basename;
                    }
                }
                if ( isset( $item_file['width'] ) && $field->fdata['ss_col_w'] >= 0 ) {
                    // assert( empty( $rows[$n][$field->fdata['ss_col_w'] + 1] ) );
                    $rows[$n][$field->fdata['ss_col_w'] + 1] = str_replace( "\t", ' ', $item_file['width'] );
                }
                if ( isset( $item_file['height'] ) && $field->fdata['ss_col_h'] >= 0 ) {
                    // assert( empty( $rows[$n][$field->fdata['ss_col_h'] + 1] ) );
                    $rows[$n][$field->fdata['ss_col_h'] + 1] = str_replace( "\t", ' ', $item_file['height'] );
                }
                if ( isset( $item_file['orient'] ) && $field->fdata['ss_col_o'] >= 0 ) {
                    // assert( empty( $rows[$n][$field->fdata['ss_col_o'] + 1] ) );
                    $rows[$n][$field->fdata['ss_col_o'] + 1] = str_replace( "\t", ' ', $item_file['orient'] );
                }
            }
        }
        // other columns from item_data
        foreach ( $item->item_data as $field_id => $field_value_arr ) {
            if ( array_key_exists( $field_id, $fields ) ){
                $field = new Ewz_Field( $field_id );
                if ( $fields[$field_id]->ss_column >= 0 ) {
                    $col = $fields[$field_id]->ss_column + 1;
                    if ( $field->field_type != 'img' ) {
                        // image columns have already been set
                        // assert(  !isset( $rows[$n][$col] ) ||  !$rows[$n][$col] );
                        if( Ewz_Settings::get_ewz_option('ss_usr_labels') ){
                            $rows[$n][$col] = esc_html( ewz_display_item( $field, $field_value_arr['value'] ) );
                        } else {
                            $rows[$n][$col] = esc_html( ( string ) $field_value_arr['value'] );
                        }
                    }


                    // append the uploaded info from the .csv file if it exists
                    // NB: <b> tag does not work here, it is overridden by the jquery dialog css
                    $info = '';
                    if ( isset( $item->item_data[$field_id]['ptitle'] ) ) {
                        $info .= '<p><span class="ui-priority-primary">Title:</span> ' . esc_html( $item->item_data[$field_id]['ptitle'] ) . "</p>";
                    }
                    if ( isset( $item->item_data[$field_id]['pexcerpt'] ) ) {
                        $info .= '<p><span class="ui-priority-primary">Caption:</span> ' .  esc_html( $item->item_data[$field_id]['pexcerpt'] ) . "</p>";
                    }
                    if ( isset( $item->item_data[$field_id]['pcontent'] ) ) {
                        $info .= '<p><span class="ui-priority-primary">Description:</span> ' .  esc_html( $item->item_data[$field_id]['pcontent'] ) . "</p>";
                    }
                    if ( isset( $item->item_data[$field_id]['ptag'] ) ) {
                        $info .= '<p><span class="ui-priority-primary">Tag:</span> ' . esc_html( $item->item_data[$field_id]['ptag'] ) . "</p>";
                    }
                    if ( $info ) {
                        // this gets passed through echo, so needs extra escaping for single quotes (?)
                        $info = str_replace( '&#039;', '\\&#039;', esc_html( $info ));
                        $info = '&#039;'. str_replace( "'", '&#039;', $info) . '&#039;';
                        // return false to stop it going to top of page when popup is closed
                        $rows[$n][$col] .= "<br><a onClick='ewz_info( $info ); return false;'>Item Info</a>";  // esc done
                    }
                }
                if ( 'str' == $field->field_type ) {
                    // initcaps any "formatted text" column
                    if ( isset($field->fdata['ss_col_fmt']) && ($field->fdata['ss_col_fmt'] >= 0) ) {
                        // assert( empty( $rows[$n][$field->fdata['ss_col_fmt']] ) );
                        // if the field is already mixed case, don't touch it
                        if ( preg_match( '/[A-Z]/', $field_value_arr['value'] ) && preg_match( '/[a-z]/', $field_value_arr['value'] ) ) {
                            $rows[$n][$field->fdata['ss_col_fmt'] + 1] = esc_html( $field_value_arr['value'] );
                        } else {
                            $rows[$n][$field->fdata['ss_col_fmt'] + 1] = ucwords( strtolower(  esc_html( $field_value_arr['value'] ) ) );
                        }
                    }
                }
            }
        }
        $user = get_userdata( $item->user_id );
        $display = Ewz_Layout::get_all_display_data();
        $custom = new Ewz_Custom_Data( $item->user_id );
        // could be done more succinctly using $$display[$xcol]['dobject']
        // but harder to understand, and fools the ide into warning
        foreach ( $extra_cols as $xcol => $sscol ) {
            if ( $sscol >= 0 ) {
                $ssc = $sscol + 1;
                $datasource = '';
                // dont crash on undefined custom data
                if( isset( $display[$xcol] ) ){
                    // assert( !isset( $rows[$n][$ssc]) || !$rows[$n][$ssc] );
                    switch ( $display[$xcol]['dobject'] ) {
                    case 'wform':
                        $datasource = $wform;
                        break;
                    case 'user':
                        $datasource = $user;
                        break;
                    case 'item':
                        $datasource = $item;
                        break;
                    case 'custom':
                        $datasource = $custom;
                        break;
                    default:
                        throw new EWZ_Exception( 'Invalid data source ' .  $display[$xcol]['dobject'] );
                    }
                    $rows[$n][$ssc] = esc_html( Ewz_Layout::get_extra_data_item( $datasource, $display[$xcol]['value'] ) );
                }
            }
        }
        ksort( $rows[$n], SORT_NUMERIC );
        ++$n;
    }
    return $rows;
}

/**
 * Return the array of defined wordpress size names
 *
 * @return  array<string> of strings
 */
function ewz_get_img_size_names() {
    $sizes = array();
    foreach ( get_intermediate_image_sizes() as $name ) {
        if( get_option( "{$name}_size_w" ) && get_option( "{$name}_size_h" ) ){
            array_push( $sizes, $name );
        }
    }
    array_push( $sizes, 'full' );
    return $sizes;
}

/**
 * Return the options string for a size selection drop-down
 *
 * @param  string  $selected  item that is to be shown as selected
 * @return string consisting of html options
 */
function ewz_get_img_size_options( $selected ) {
    $options = '<option value="">--- Select Image Size ---</option>';
    foreach ( ewz_get_img_size_names() as $size ) {
        $sel = '';
        if( $size == $selected ){
            $sel = ' selected="selected"';
        }
        $options .= '<option value="' . esc_attr( $size ) . '"' . $sel . ">$size</option>";
    }
    return $options;
}

/**
 * Return a function to be used to sort the array
 *
 * @param   int    $sort_col  column to sort on (numeric, 0-based)
 * @param   string $sort_order   'asc' or 'desc'
 * @return  closure
 */
function ewz_item_list_sort( $sort_col, $sort_order ){

    return function($a, $b) use ( $sort_col, $sort_order ) {
        if( $sort_order == 'asc' ){
            return strcmp( $a[$sort_col], $b[$sort_col] );
        } else {
            return  strcmp( $b[$sort_col], $a[$sort_col] );
        }
    };
}

/** ************************** Main Item List Function ********************************
 * Generates the management page that lists uploaded items
 *
 * Checks for input data, validates, sanitizes and processes it
 * Then outputs the page
 *
 * @return void
 */

function ewz_list_items() {
    $data = array_merge( $_POST, $_GET );    // this is normally accessed via GET
    if ( !( isset( $data['webform_id'] ) &&
    Ewz_Permission::can_manage_webform( $data['webform_id'], 0 ) ) ){
        wp_die( "Insufficient Permissions To View Page" );
    }
    // if errors here stop processing
    try{
        $input = new Ewz_Item_List_Input( $data );
        $requestdata  = $input->get_input_data();
    } catch( Exception $e ){
        wp_die( $e->getMessage() );
    }

    // Do any bulk actions requested
    $the_action = -1;
    if( isset( $requestdata['action'] ) ){
        $the_action = $requestdata['action'];
        if( $the_action == -1 ){
            $the_action = $requestdata['action2'];
        }
    }
    $requestdata['the_action'] = $the_action;
    unset($requestdata['action']);
    unset($requestdata['action2']);

    $message = '';
    // Messages from exceptions generated here are  are shown to user
    if( $the_action == 'ewz_attach_imgs' ){
        ewz_show_wait_cursor();
        $message = ewz_check_and_attach_imgs();
    } elseif(  $the_action == 'ewz_batch_delete_all' ){
        ewz_show_wait_cursor();
        $message = ewz_batch_delete_items( true );
    } elseif(  $the_action == 'ewz_batch_delete_data' ){
        ewz_show_wait_cursor();
        $message = ewz_batch_delete_items( false );
    } elseif(  $the_action == 'ewz_save_edits' ){
        ewz_show_wait_cursor();
        ewz_save_admin_edits( $requestdata );
    }
    // if errors here stop processing
    try{
        ewz_display_list_page( $message, $requestdata );
    } catch( Exception $e ){
        wp_die( $e->getMessage() );
    }
}

/**
 * Show an overlay with a wait cursor while the output is being generated
 * Not sure if this is really good practice, but only way I can work out to do it
 * @return void
 **/
function  ewz_show_wait_cursor(){
    ob_start();
    echo "<div id='ewz_overlay'><img alt='Please Wait' src='" . plugins_url( 'images/loading1.gif', dirname(__FILE__) ) . "'></div>";
    ob_end_flush();
    while ( @ob_end_flush() );
    flush();
}

/**
 * @param array<mixed>  $requestdata
 *
 * @return void
 */
function ewz_save_admin_edits( $requestdata ){
    foreach( $requestdata['ewz_check'] as $n => $item_id ){
        $rdata = $requestdata['rdata'][$n];
        $item = new Ewz_Item( $item_id );

        foreach( $rdata as $field_key => $val ){
            $item->item_data[$field_key]['value'] = $val;
        }
        $item->save();
    }
}


/**
 * Return the html for the display of the criteria used to select the items
 *
 * @param  array<mixed>  $field_opts   of fields and their selected values
 * @param  array<mixed>  $custom_opts   of fields and their selected values
 * @param  array<mixed>  $extra_opts   show only items uploaded within the last $uploaddays
 *
 * @return string  html
 *
 * NB: needs escaping here because it contains html
 */
function  ewz_get_opt_display_string( $field_opts, $custom_opts, $extra_opts ){

    $optname = array();
    $optval = array();
    if ( $field_opts ) {
        foreach( $field_opts as $field_id=>$fval ){
            $field = new Ewz_Field($field_id);
            $optname[$field_id] = esc_html( $field->field_header );
            $optval[$field_id] = str_replace( '~*~', 'Any', str_replace( '~+~', 'Not Blank', str_replace( '~-~', 'Blank', esc_html( $fval ) ) ) );
        }
    }
    if ( $custom_opts ) {
        foreach( $custom_opts as $custom_name=>$cval ){
            $optname[$custom_name] = esc_html( Ewz_Custom_Data::$data[$custom_name] );
            $optval[$custom_name] = str_replace( '~*~', 'Any', str_replace( '~+~', 'Not Blank', str_replace( '~-~', 'Blank', esc_html( $cval ) ) ) );
        }
    }

    $str ="<ul>\n";
    foreach ( $optname as $f => $name ) {
        $str .= '<li>' . esc_html( "$name = $optval[$f]" ) . "</li>\n";
    }
    foreach ( $extra_opts as $nm => $val ) {
        if( $nm == 'uploaddays' && $val > 0 ){
            $str .=  '<li>' . esc_html("Uploaded in the last $val days") . "</li>\n";
        }
    }
    $str .= "</ul>\n";
    return $str;
}


/**
 * Return the html for the items-per-page form
 *
 * @param   string    $help_icon
 * @param   string    $url
 * @param   int       $ipp   value set for "items per page"
 * @return  string html
 */
function ewz_get_ipp_form( $help_icon, $url, $ipp ){
    $str = '<form id="ipp_form" class="ewz_shaded" action="' . esc_url( $url ) . '" method="POST" >';
    $str .= '<img  class="ewz_ihelp" src="' . $help_icon . '" onClick="ewz_help(\'numimgs\')";>&nbsp;';
    $str .= 'Show on screen ';
    $str .= '    <input type="hidden" name="action" value="ewz_set_ipp">';
    $str .= '    <input id="ewz_ipp" class="screen-per-page" type="number"  value="' .  esc_attr( "$ipp" ) . '"';
    $str .= '          " maxlength="3" name="ewz_ipp" max="999" min="1" step="1">';
    $str .= '    <label for="ewz_ipp"> Items </label>';

    // processIPP does an ajax post call followed by a document reload
    $str .= '    <button  type="submit" id="ewz-ipp-apply"  onClick="return processIPP(\'ipp_form\')" class="button action">Apply</button>';
    $str .= "</form>\n";

    return $str;
}

/**
 * @param string   $help_icon
 * @param array<mixed>    $attach_prefs
 * @param array<mixed>    $image_columns
 *
 * @return string
 */
function ewz_attach_options_string( $help_icon, $attach_prefs, $image_columns ){
    $dropdown = wp_dropdown_pages( array( 'name'=>'ewz_page_sel', 'selected'=>$attach_prefs['ewz_page_sel'],
    'echo'=>0, 'show_option_none' => '--- Select Page ---') );
    $size_args = ewz_get_img_size_options( $attach_prefs['img_size'] );
    $default_qual = isset( $attach_prefs['img_qual'] ) ?  $attach_prefs['img_qual'] : Ewz_Settings::get_ewz_option('attach_jpeg_qual');
    $qual_args = '';
    foreach( Ewz_Settings::get_jpeg_quality_opts() as $val => $display ){
        $sel = ( $default_qual == $val ) ? ' selected="selected"' : '';
        $qual_args .= "<option value=$val $sel>$display</option>";   // no esc needed
    }
    $esc_cmt_chkd = $attach_prefs['img_comment'] ? 'checked' : '';
    $esc_dups_chkd = $attach_prefs['dups_ok'] ? 'checked' : '';
    $warn = $esc_dups_chkd ? '<span style="font-size: 1.5em;"> * &nbsp; * &nbsp; * </span>' : '';
/* NB: Older versions of php require no spaces after the semicolon at the end of a heredoc */
    $str =<<<EOF

    <table class="ewz_itemlist_opts" style="float:left;  margin-bottom:20px; border: 1px dotted black;">
        <tr><td colspan="2"style="padding-left: 5px; text-align: center;"> <h3>Parameters for attaching images to pages</h3> </td>
            </tr>
        <tr><td  style="padding-left: 5px;"><img  class="ewz_ihelp" src="$help_icon" onClick="ewz_help('dest');">&nbsp;
                        Destination page when attaching images: </td>
            <td>$dropdown </td></tr>
        <tr><td style="padding-left: 5px;"><img  class="ewz_ihelp" src="$help_icon" onClick="ewz_help('imgcomm');">&nbsp;
                        Allow comments on attached images:  </td>
            <td><input type="checkbox" id="img_comment" value="1" name="img_comment" $esc_cmt_chkd>
              </td></tr>
        <tr><td style="padding-left: 5px;"><img  class="ewz_ihelp" src="$help_icon" onClick="ewz_help('attachsize');">&nbsp;
                        Size of attached image<br> &nbsp; &nbsp; &nbsp; &nbsp; <span class="ewz_inotes">(best size will depend on your theme)</span>: </td>
            <td><select id="img_size" name="img_size" >$size_args</select></td></tr>
        <tr><td style="padding-left: 5px;"><img  class="ewz_ihelp" src="$help_icon" onClick="ewz_help('imgqual');">&nbsp;
                        Image quality for attachment <br> &nbsp; &nbsp; &nbsp; &nbsp; <span class="ewz_inotes">( sets the jpeg compression )</span>: </td>
            <td><select id="img_qual" name="img_qual" >$qual_args</select></td></tr>
        <tr><td style="padding-left: 5px;"><img  class="ewz_ihelp" src="$help_icon" onClick="ewz_help('attachtext');">&nbsp;
                        Optional default text for attached image</span>: </td>
EOF;
/* NB: Older versions of php require no spaces after the semicolon at the end of a heredoc */

    $str .= '  <td><table class="ewz_field">';
    $str .= '                      <tr>';
    $str .=                         '<td>Title: </td>';
    $str .=                         "<td><input type='text' id='ewz_btitle' name='btitle' maxlength='80'></td>";
    $str .=                       '</tr>';
    $str .=                       '<tr>';
    $str .=                         '<td>Excerpt ( Caption ): </td>';
    $str .=                          "<td><input type='text' id='ewz_bexcerpt' name='bexcerpt' maxlength='120'></td>";
    $str .=                       '</tr>';
    $str .=                       '<tr>';
    $str .=                          '<td>Description: </td>';
    $str .=                          "<td><input type='text' id='ewz_bcontent' name='bcontent' maxlength='500'></td>";
    $str .=                       '</tr>';
    $str .=                   '</table>';
    $str .=        '</td>';
    $str .=   '</tr> ';

    if ( count( $image_columns ) > 1 ) {
        $info = '<img  class="ewz_ihelp" src="' . $help_icon. '" onClick="ewz_help(\'multi\');">&nbsp;';
        foreach ( $image_columns as $fld_id => $fld_head ) {
            $col_checked = '';
            if( isset( $attach_prefs['ifield'] ) && ( $attach_prefs['ifield'] == $fld_id ) ){
                $col_checked = 'checked';
            }
            $eschead = esc_html( $fld_head );
            $str .= "<tr><td>$info Attach images from column $eschead</td>";   // esc done
            $str .= '    <td><input type="radio" name="ifield" value="' . esc_attr( $fld_id ). '" ' . $col_checked . '></td>';
            $str .= '</tr>';
            $info = ' &nbsp; &nbsp; &nbsp; &nbsp; ';
        }

    }

    $str .=  '<tr><td style="padding-left: 5px;"><img  class="ewz_ihelp" src="' . $help_icon . '" onClick="ewz_help(\'dups_ok\');">&nbsp;';
    $str .=  'Allow an image to be attached more than once</td>';
    $str .=  '<td><input type="checkbox" id="dups_ok" value="1" name="dups_ok" ' . $esc_dups_chkd . " > &nbsp; $warn</td></tr>";

    $str .= '</table>';
    if ( count( $image_columns ) <= 1 ) {
        foreach ( $image_columns as $fld_id => $fld_head ) {
            $eschead = esc_html( $fld_head );
            $str .= '<input type="hidden" name="ifield" value="' . esc_attr( $fld_id ) . '">';
        }
    }
    return $str;
}

/**
 * Generate the required data and then print the html for the item list page
 *
 * @param   string  $message       Message for user - validation errors or feedback on actions taken
 * @param   array<mixed>   $requestdata   $_GET plus $_POST, validated
 * @return  void
 */
function  ewz_display_list_page( $message, $requestdata ){

    $webform_id = $requestdata['webform_id'];

    $webform = new Ewz_Webform( $webform_id );

    $fields = Ewz_Field::get_fields_for_layout( $webform->layout_id, 'ss_column' ) ;

    $field_opts = array();
    if ( isset( $requestdata['fopt'] ) ) {
        $field_opts = $requestdata['fopt'];
    }
    $custom_opts = array();
    if ( isset( $requestdata['copt'] ) ) {
        $custom_opts = $requestdata['copt'];
    }
    $extra_opts = array();             // this is set up to allow for other options than just uploaddays
    if( isset( $requestdata['uploaddays'] ) ){
        $extra_opts['uploaddays'] = $requestdata['uploaddays'];
    }

    $extra_cols = Ewz_Layout::get_extra_cols( $webform->layout_id );

    $items_for_edit = ( $requestdata['the_action'] == 'ewz_select_for_edit' ) ? $requestdata['ewz_check'] : array();

    $items = array();
    $headers = array();
    if( $items_for_edit ){
        $headers = ewz_get_headers_for_edit( $fields );
        $items = array_map( function($v){ return new Ewz_Item( $v ); }, $items_for_edit );
        $rows = ewz_get_item_rows_for_edit( $items, $fields, $webform, $items_for_edit );        // has been html-escaped
    }  else {
        $headers = ewz_get_headers( $fields, $extra_cols );
        $items = Ewz_Item::filter_items( $field_opts, $custom_opts, $extra_opts,
        Ewz_Item::get_items_for_webform( $webform_id, 0 ) );
        $rows = ewz_get_item_rows( $items, $fields, $extra_cols, $webform );        // has been html-escaped
    }
    if( isset( $requestdata['orderby'] ) && isset( $requestdata['order'] ) ){
        uasort( $rows, ewz_item_list_sort( $requestdata['orderby'], $requestdata['order'] ) );
    }

    $item_ids = array_map( function($v){ return $v->item_id; },  $items );

    $ewzG = array(
        'message'    => esc_html( $message ),
        'load_gif'   => plugins_url( 'images/loading1.gif', dirname(__FILE__) ),
        'helpIcon'   => plugins_url( 'images/help.png' , dirname(__FILE__) ),
        'display_for_edit' => ( $requestdata['the_action'] == 'ewz_select_for_edit' ),
    );
    if( $requestdata['the_action'] == 'ewz_save_edits' ){
        $ewzG['do_refresh'] = true;
    }

    wp_localize_script( 'ewz-admin-list-items', 'ewzG',  $ewzG  );
    // script name set above in ewz_item_list_scripts

    // image columns dont pick up width, have to force it
    $style = '';
    foreach( ewz_get_img_cols( $fields ) as $field_id => $col ){
        $n = $fields[$field_id]->ss_column + 1;
        $style .= "th.column-$n{width: " . ( get_option('thumbnail_size_w') + 10 ) . 'px;}';
    }
    // needed to generate html below:
    $attach_prefs       = ewz_html_esc( $webform->get_attach_prefs() );
    $ewz_item_list      = new Ewz_Item_List( $item_ids, ewz_html_esc($headers), $rows, $ewzG['display_for_edit'] );
    $formtitle          = $webform->webform_title;
    $help_icon          = plugins_url( 'images/help.png' , dirname(__FILE__) );
    $ipp                = get_user_meta( get_current_user_id(), 'ewz_itemsperpage', true );
    $listurl            = admin_url( "admin.php" );
    $esc_opt_display    = ewz_get_opt_display_string( $field_opts, $custom_opts, $extra_opts );
    $webformsurl        = admin_url( 'admin.php?page=entrywizard' . "&openwebform=$webform_id" );
    $image_columns      = ewz_get_img_cols( $fields );

?>
    <style type="text/css"><?php print esc_attr($style); ?></style>

    <div class="ewz_showlist">
    <h2>Images and Stored Information for "<?php print esc_html( $formtitle ); ?>"</h2>
    <div id="info-text" class="wp-dialog"> </div>

    <div class="ewz_params">
    <br>
<?php print ewz_get_ipp_form( $help_icon, $listurl, $ipp ); ?>
    <br>
<u>Displaying:</u> <?php print $esc_opt_display; ?>
</div>
<form id="ewz_list_form" action="" method="POST" onSubmit="return processForm('ewz_list_form')">
<div id="ewz_numc"><?php wp_nonce_field( 'ewzadmin', 'ewznonce' ); ?></div>
<div class="ewzform">
<?php
if( $ewzG['display_for_edit'] ){
    wp_nonce_field( 'ewzupload', 'ewzuploadnonce', true, true );
}
?>

<input type="hidden" name="webform_id" id="webform_id" value="<?php print esc_attr( $webform_id ); ?>">

<?php print ewz_attach_options_string( $help_icon, $attach_prefs, $image_columns ); ?>

<div id='message'></div>

<?php $ewz_item_list->display(); ?>

<p class="ewz_pcentre ">
<button type="button" class="button-primary" id="backButton"
onClick="window.location='<?php print esc_url( $webformsurl ); ?>';">
    Back to WebForms Page</button>
</p>
</div>
</form>
</div>

<div id="help-text" style="display:none">
<!-- HELP POPUP Item List ~ Main Options ~ Destination  -->
     <div id="dest_help" class="wp-dialog" >
<p>Images that have been "attached" to a page may be displayed on the page in a regular
wordpress gallery, or in other ways depending on what plugins you have.</p>
<p>-------------------------------</p>
<p><b>Important Note:</b> Images attached to pages are copied from the entrywizard uploaded image, and from then on
are no longer accessible from entrywizard.
    The user who originally uploaded the image is assigned as the "author" of the copy</p>
<p>This means that:
<ol><li>If the image is deleted from EntryWizard (by the user or by the admin using this page), the
attached copy remains on the page it was attached to.</li>
<li>If the user who originally uploaded the image is subsequently
deleted from the wordpress installation, you will be asked whether to delete the user's "content" or assign
                        it to another user as "author".  <i>The content referred to would include any such copied images.</i></li>
                    <li>In WordPress 4.9.6 a new "Export Personal Data" facility was introduced. This function lists the
                        exported images as part of the user's personal data, but <b>not</b> their associated title,
    caption or description.</li>
</ol>
<p>-------------------------------</p>

<p>To set up the gallery, include the shortcode <b>"[gallery]"</b> on your page where you wish the
gallery to appear.  If your theme has not overridden the default behaviour, this will display
    in the page thumbnails of all the attached images, which link to larger versions. If you have
    uploaded a .csv file of image data, it's contents will determine the headers and captions of the
               images.</p>
            <p>Your theme determines the format of the gallery.  The "twentyeleven" theme shows a gallery that
            displays the title and caption below the thumbnail, and the title, caption and description on the image
            page it links to.  Some other themes may not display all three  pieces of text with each image.
            Some may display the text only on mouseover. ( If you know how to do it, you can often change the
            look of the gallery by adding css using either a child theme or a css plugin. )</p>

            <p> <i><b>NB:</b> The Wordpress gallery functionality is in the process of changing.
               Currently there are two formats for the shortcode:
           <ul><li>[gallery]  ( with optional parameters like the number of columns ). In this form,
                   the gallery displays all images currently attached to the page. </li>
               <li>[gallery ids="n1, n2, n3 ...."] where n1 n2 etc are the id's of the images to
display. Only the specified images are displayed, and they do not need to be
                                                                  attached to the page.</li>
</ul> EntryWizard currently assumes the first format.</i>

As of wordpress version 3.5, once the gallery content has been changed using the Wordpress
    editor, the shortcode will
    automatically be put in the "list of images" format, and newly attached images will
    not be displayed in the gallery.
    This may be changed by using the "text" tab in the page editor to change the gallery
    shortcode back to the first format.</p>
<p>For documentation about the gallery shortcode, see
  http://codex.wordpress.org/Gallery_Shortcode.</p>
  <p>-------------------------------</p>
  <p>If you wish the gallery to display scores or other image-specific information not
  uploaded by the member, you need first
      to upload a csv file containing this data, using the "Upload extra <u>per-image</u> data" button on
      the "Webforms" page. Make sure that you put the text into the title, caption and/or description
      depending on which your theme actually displays.</p>
  </div>
  <!-- HELP POPUP  Item List ~ Main Options ~ Allow Comments  -->
       <div id="imgcomm_help" class="wp-dialog" >
  <p>If this is checked, anyone with permission to see the destination page will be allowed
  to add comments to the image. </p>
  <p>The default value for this option is set in the EWZ Settings page.</p>
  </div>
  <!-- HELP POPUP Item List ~ Main Options ~  Attached Image Size  -->
       <div id="attachsize_help" class="wp-dialog" >
  <p>"Attaching" creates a copy of the image which is added to the Wordpress media.  This
  allows the attached copy to be deleted or modified using the normal wordpress interface,
      without affecting the entrywizard file.</p>
  <p>You may, if you like, choose to make this copy a smaller version of the uploaded image
  instead of the full-size one. In fact, if your theme does not make use of the full uploaded size,
                                                     you will be wasting time and bandwidth if you do not resize to something that fits your theme.</p>
  <p>On the other hand, the resizing does take some time during the attachment process. </p>
  <p>Select "full" to copy the original uploaded image. </p>
  <p>The copy is created in your normal uploads directory, so it will not be deleted if you
  should uninstall entrywizard.  Editing or deleting the copy should have no effect on
      the image stored in EntryWizard.</p>
  <p>The default value for this option is set in the EWZ Settings page.</p>
  </div>
  <!-- HELP POPUP Item List ~ Main Options ~ Image Quality  -->
       <div id="imgqual_help" class="wp-dialog" >
  <p>Until version 4.5, Wordpress defaulted to setting a jpeg quality of 90% when resizing
  images. With version 4.5, the default was lowered to 82%. If you find the quality reduction is noticeable,
      ( or if you do not need such a high quality ), you may set the value here.</p>
  <p>Of course, higher image quality means large image files, so pages will be slower
  to download. </p>
  <p>The default value for this option is set in the EWZ Settings page.</p>
  </div>
  <!-- HELP POPUP Item List ~ Main Options ~ Attachment Text  -->
       <div id="attachtext_help" class="wp-dialog" >
  <p>When an image is "attached" to a wordpress page, a new individual "attachment page" is created for the image.
  Like all wordpress pages, the attachment page may have three pieces of text associated with it:
      Title, Excerpt and Content. Exactly how and where these are displayed depends on your theme.  </p>
  <p>If the information you wish to display in these fields is already available in the table below, you may set those values here.
  In the text you enter, "[~n]" will be replaced, for each item, by the value in the nth column  below (numbers are in parentheses, empty columns do not appear).</p>
  <p>e.g. If column 3 contains a title for the image, and column 7 contains the photographer's name,
             then
             "[~3] by [~7]" will result in something like "My Beautiful Image by Jane Doe".</p>

        </div>
        <!-- HELP POPUP Item List ~ Main Options ~  Attaching More Than Once  -->
        <div id="dups_ok_help" class="wp-dialog" >
           <p>If you have a lot of images, it's fairly easy to mistakenly select one that has already been attached.
  EntryWizard will only attach it a second time to the same page if you check this box.</p>
  <p>But attaching creates new copies of the images, and EntryWizard does not keep track of those.  If you
  delete or unattach one of the attachment copies for some reason, and wish to re-attach the image, you would need to
                                                               check this box to override the normal behaviour.</p>
  </div>
  <!-- HELP POPUP Item List ~ Main Options ~  Multiple Images  -->
       <div id="multi_help" class="wp-dialog" >
  <p>Only images from one column may be attached in one action. If you have more than one image column,
  you need to select one.</p>
  </div>
  <!-- HELP POPUP Item List ~ Show on Screen  -->
       <div id="numimgs_help" class="wp-dialog" >
  <p>Attaching images to a page requires resizing on the server, which may take some time. You will
  probably need to do only a few at a time to avoid timeout errors.</p>
  <p>Setting this value will make it easier to do a few at a time and keep track of what has been done.</p>
  <p>It may also be useful to set an increased max_execution_time in your .htaccess file.</p>
  </div>
  <!-- HELP POPUP Item List ~ Bulk Actions  -->
       <div id="bulk_help" class="wp-dialog" >
  <p>The option to "Edit the uploaded data for selected items" was added with version 1.3.14.</p>
  <p>It allows the administrator to edit the data that was entered in the layout fields by the user. </p>
  <p>Use the left-hand check boxes to select the items you wish to edit, select "Edit the uploaded data ..."
  from the  Bulk Actions menu, then click 'Apply'.
      A new page will show only your selected items and their layout fields, in editable form.</p>
  <p>In the new edit page, make your changes, then select "Save changes ...." from the Bulk Actions menu and click "Apply".
  ( After editing, you will be returned to the first page no matter which page you were on before. )</p>
  <p>Please note:</p>
  <ul>
  <li>In the edit view, changes to <b>All</b> editable items will be saved, even if you do not check the left-hand box.
  To back out of a change, either manually revert to the original values, or reload the page without saving. </li>
  <li><b>Restrictions will not be enforced.</b></li>
  </ul>
  <hr>
  <p>The option to "Delete Selected Item Data Only" was added with version 1.2.21 along with the batch entry uploader</p>
  <p>Normally, you would want to delete an item's image file(s) along with its data.
               If using the batch entry uploader, however, it is possible you may not want the image deleted, just the data you uploaded.</p>
        </div>

    </div>

<?php

}
