<?php
/*
Plugin Name: Inline Record Editor
Description: Allows editing of records directly from the section listing page
Version: 1.00
Requires at least: 2.04
*/

//  BY DEFAULT THIS PLUGIN WILL APPLY TO ALL TABLES
$GLOBALS['IRE_TABLES'] = '__all__';

//  TO ONLY USE THIS PLUGIN WITH CERTAIN TABLES, UNCOMMENT THE
//  FOLLOWING LINE AND ADD THE TABLE NAMES TO NAME TO THE LIST.
// $GLOBALS['IRE_TABLES'] = array();


// DON'T EDIT ANYTHING BELOW THIS LINE

addFilter( 'listRow_displayValue', '_ire_listRow_displayValue', null, 4 );
addFilter( 'list_advancedCommands', '_ire_list_advancedCommands', null, 1 );
addAction( 'section_unknownAction', '_ire_saveAllChanges', null, 2 );
addAction( 'init_complete', '_ire_init_complete', null, null );

function _ire_init_complete() {
  global $APP;
  if ( @$_REQUEST['bulksave'] ) {
    $APP['notices'] = 'All shown records updated';
  }
}

function _ire_saveAllChanges( $tableName, $action ) {
  if ( $action != 'bulkEdit' ) return;
  if ( $GLOBALS['IRE_TABLES'] != '__all__' && !in_array($tableName, $GLOBALS['IRE_TABLES'] ) ) return;

  global $TABLE_PREFIX;

  $queries = array();

  foreach( $_REQUEST as $k => $v ) {
    if ( strpos( $k, 'ire__' ) === 0 ) {
      list( $ire, $fieldname, $num ) = explode( '__', $k );
      if ( !@$queries[$num] ) {
        $queries[$num] = array();
      }
      if ( $GLOBALS['schema'][$fieldname]['type'] == 'checkbox' ) {
        // we are actually looking at a hidden field; replace the value with that of the checkbox, if one was submitted
        $v = @$_REQUEST["checkbox__{$fieldname}__$num"] ? 1 : 0;
      }
      $queries[$num][] = "`$fieldname`='" . mysql_escape($v) . "'";
    }
  }

  foreach ( $queries as $num => $q ) {
    $query = "UPDATE {$TABLE_PREFIX}{$tableName} SET ";
    for ( $i=0; $i<count($q); $i++ ) {
      $query .= $q[$i]; 
      if ( $i+1 < count($q) ) $query .= ',';
    }  
    $query .= " WHERE num='" . mysql_escape($num) . "'";
    mysql_query( $query ) or die( 'Could not execute bulk update: ' . mysql_error() );
  }

  header( 'Location: admin.php?bulksave=true&menu=' . $tableName );
}

function _ire_list_advancedCommands( $labelsToValues ) {
  $tableName = @$_REQUEST['menu'];
  if ( $GLOBALS['IRE_TABLES'] != '__all__' && !in_array( $tableName, $GLOBALS['IRE_TABLES'] ) ) return $labelsToValues;
  $labelsToValues['Save All Changes'] = 'bulkEdit';
  return $labelsToValues;
}


function _ire_listRow_displayValue( $displayValue, $tableName, $fieldname, $record ) {
 
  if ( $GLOBALS['IRE_TABLES'] != '__all__' && !in_array( $tableName, $GLOBALS['IRE_TABLES'] ) ) return $displayValue;
  $type = $GLOBALS['schema'][$fieldname]['type'];

  if ( $type == 'checkbox' ) {
    // display a checkbox
    $displayValue = '<input type="checkbox"';
    $displayValue .= ' name="checkbox__' . $fieldname . '__' . $record['num'] . '"';
    if ( $record[$fieldname] ) {
      $displayValue .= ' checked="true"';
    }
    $displayValue .= ' value="1" />';
    // also include a hidden field so that we know if this record exists but hasn't been checked
    $displayValue .= '<input type="hidden" name="ire__' . $fieldname . '__' . $record['num'] . '" value="1"/>';
  }

  if ( $type == 'list' && $GLOBALS['schema'][$fieldname]['listType'] == 'pulldown' ) {
    // display a dropdown
 
    $displayValue = '<select name="ire__' . $fieldname . '__' . $record['num'] . '">';
    $displayValue .= '</select>';

    $displayValue = _ire_showPulldown( $GLOBALS['schema'][$fieldname], $fieldname, $record );
  }

  // return the display value, which may have been overridden
  return $displayValue;
}

function _ire_showPulldown($fieldSchema, $fieldname, $record) {
 
   // set field attributes
   $listOptions = getListOptionsFromSchema($fieldSchema, $record);
   $valignTop   = ($fieldSchema['listType'] != 'pulldown') ? 'style="vertical-align: top;"' : '';
 
   // get field value
   if      ($record)                                 { $fieldValue = @$record[ $fieldname ]; }
   else                                              { $fieldValue = ''; }
   $fieldValues = preg_split("/\t/", $fieldValue, -1, PREG_SPLIT_NO_EMPTY); // for multi value fields
   $encodedValue  = htmlspecialchars($fieldValue);
 
   // get list of values in database that aren't in list options (happens when list values are removed or field
   // ... was a textfield than switched to a pulldown that doesn't offer all the previously entered values as options
   $fieldValuesNotInList = array();                                                                                                                       
   $listOptionValues = array();
   foreach ($listOptions as $optionArray) {
     list($value,$label) = $optionArray;
     $listOptionValues[] = $value;
   }
   $fieldValuesNotInList = array_diff($fieldValues, $listOptionValues);
   $noLongerInListText   = (count($fieldValuesNotInList) > 1) ? t('Previous selections (no longer in list)') : t('Previous selection (no longer in list)'     );
 
   // pulldown
   $select = '';
   $select .= "  <select name='ire__{$fieldname}__{$record['num']}'>\n";
   $select .= "  <option value=''>&lt;select&gt;</option>\n";
   foreach ($listOptions as $optionArray) {
     list($value,$label) = $optionArray;
     $encodedValue = htmlspecialchars($value);
     $selectedAttr = selectedIf($value, $fieldValue, true);
     $encodedLabel = htmlspecialchars($label);
     $select .= "<option value=\"$encodedValue\" $selectedAttr>$encodedLabel</option>\n";
   }
 
   // show database values not in current list options
   if ($fieldValuesNotInList) {
     $select .= "  <optgroup label='$noLongerInListText'>\n";
     foreach ($fieldValuesNotInList as $value) {
       $select .= "    <option value=\"" .htmlspecialchars($value). "\" selected='selected'>" .htmlspecialchars($value). "</option>\n";
     }
     $select .= "  </optgroup>\n";
   }
 
   $select .= "  </select>\n";
   return $select;
}

?>
