<?php
/**
* FlatFiles - flat files operations
* @access   public 
* @version  0.2.4
* @require  FileJobs
* @require  Trash
*/
class FlatFiles extends FileJobs
{
	var $aRow;
	var $sTxt;
  var $sString;
  var $rFile;
  var $mData;
	var $sSeperator   =	'$';
	var $sBreak       = "\n";
  var $iEol         = 50000;
  var $iExp         = 20;
  var $bSortNumeric = null;
  var $bLock        = null;

  /**
  * Set array to $this->aRow = $aData variable
  * @return void
  * @param array $aData
  */
  function setRow( $aData ){
    $this->aRow = $aData;
  } // end function setRow

  /**
  * Set $this->bLock variable as true
  * If this variable is true then all opened files
  * will be blocked after fopen
  * @return void
  */
  function setLock( ){
    $this->bLock = true;
  } // end function setRow

  /**
  * Set parameters limit to $this->iEol
  * @return void
  * @param array $iEol
  */
  function setEol( $iEol ){
    $this->iEol = $iEol;
  } // end function setEol

  /**
  * Set sort type to $this->bSortNumeric variable
  * @return void
  * @param array $iEol
  */
  function setSortNumeric( ){
    $this->bSortNumeric = true;
  } // end function setSortNumeric

  /**
  * Set indexes limit to $this->iExp variable
  * @return void
  * @param array $iExp
  */
  function setExp( $iExp ){
    $this->iExp = $iExp;
  } // end function setExp

  /**
  * Set $this->mData variable with mixed content
  * @return void
  * @param mixed  $mData
  */
  function setData( $mData ){
    $this->mData = $mData;
  } // end function setData

  /**
  * Set string to $this->sString variable
  * This variable contains string and it will be saved to file
  * @return void
  * @param string $sText
  */
  function setString( $sText ){
    $this->sString = $sText;
  } // end function setString

	/**
  * Open file and lock it $this->bLock variable is true
  * @return int
  * @param string $sAtrybut
  */
	function openFile( $sAtrybut ){
		$this->rFile = fopen( $this->fileName, $sAtrybut );
    if( isset( $this->bLock ) )
      flock( $this->rFile, LOCK_EX );
	} // end function openFile
	
	/**
  * Close file and unlock
  * @return void
  */
	function closeFile( ){
    if( isset( $this->bLock ) ){
      flock( $this->rFile, LOCK_UN );
      $this->bLock = null;
    }
		fclose( $this->rFile );
	} // end function closeFile

  /**
  * Execute functions to save data to file 
  * @return null
  * @param string $sFile
  * @param string $sOption
  * @param string $sAttribute
  */
  function addToFile( $sFile = null, $sOption = 'end', $sAttribute = 'a' ){
		if( isset( $sFile ) )
			$this->setFileName( $sFile );	
		if( isset( $this->aRow ) && is_array( $this->aRow ) )
			$this->sTxt = implode( $this->sSeperator, $this->aRow ).$this->sSeperator;
		else 
			$this->sTxt = $this->sString;
    if( ereg( 'sort', $sOption ) ){
      $this->saveData( $sOption );
    }
    else{
			$this->openFile( $sAttribute );
			$this->addToEnd( );
    }
		$this->closeFile( );
		unset( $this->mData, $this->aRow, $this->sString );
	} // end function addToFile

  /**
  * Save data to file and sort it
  * Require defined variable: $this->mData
  * @return void
  * @param string $sSortFunction
  * @param mixed  $mValue
  * @param int    $iPosition
  */
  function saveData( $sSortFunction = 'sort', $mValue = null, $iPosition = 0 ){

    $aFile = file( $this->fileName );
    $this->openFile( 'w' );

    if( !isset( $this->mData ) || !is_array( $this->mData ) ){
      $iCount= substr_count( $this->sTxt, '$' );
      for( $i = 0; $i < $iCount; $i++ ){
        $this->mData[] = $i;
      } // end for
    }

    if( !isset( $mValue ) )
      $aFile[] = $this->sTxt;

    $iCount = count( $aFile );
    $iCount2= count( $this->mData );

    if( $this->throwExtOfFile( $this->fileName ) == 'php' ){
      $sSaveFirst = rtrim( $aFile[0] );
      $iStart = 1;
    }
    else
      $iStart = 0;

    for( $i = 0; $i < $iCount2; $i++ ){
      $aDataAfter[] = array_search( $i, $this->mData );
    } // end for

    $i3 = 0;
    for( $i = $iStart; $i < $iCount; $i++ ){
      $aData = explode( $this->sSeperator, rtrim( $aFile[$i] ) );

      if( isset( $mValue ) && $aData[$iPosition] == $mValue ){
        $aData = explode( $this->sSeperator, rtrim( $this->sTxt ) );
      }
      for( $i2 = 0; $i2 < $iCount2; $i2++ ){
        $aSave[$i3][$i2] = $aData[$this->mData[$i2]];
      } // end for
      $i3++;
    } // end for

    if( isset( $sSortFunction ) )    
      $sSortFunction( $aSave );

    for( $i = 0; $i < $iCount; $i++ ){
      $sSave = null;

      if( $i == 0 && isset( $sSaveFirst ) ){
        $sSave .= $sSaveFirst.$this->sBreak;
        $iCount--;
      }

      for( $i2 = 0; $i2 < $iCount2; $i2++ ){
        $sSave .= $aSave[$i][$aDataAfter[$i2]].$this->sSeperator;
      } // end for
      
      fwrite( $this->rFile, $sSave.$this->sBreak );
    } // end for

  } // end function saveData

  /**
  * Save data to end of file
  * @return bool
  */
	function addToEnd( ){
    fwrite( $this->rFile, $this->sTxt.$this->sBreak );
	} // end function addToEnd

  /**
  * Return last id of file
  * @return int
  * @param string $sFile
  * @param int    $iPosition
  */
  function throwLastId( $sFile, $iPosition = 1 ){
    $this->setFileName( $sFile );

    if( is_file( $this->fileName ) ){
      $aFile  = file( $this->fileName );
      $iCount = count( $aFile );
      $iMax   = 0;
      if( $this->throwExtOfFile( $this->fileName ) == 'php' )
        $iStart = 1;
      else
        $iStart = 0;
      for( $i = $iStart; $i < $iCount; $i++ ){
        $aExp = explode( $this->sSeperator, $aFile[$i] );
        if( $aExp[$iPosition] > $iMax )
          $iMax = $aExp[$iPosition];
      } // end for
      return $iMax;
    }
    else
      return null;
  } // end function throwLastId


  /**
  * Return file in array
  * @return array
  * @param string $sFile
  * @param string $sSort
  */
  function throwFileArray( $sFile = null, $sSort = null ){
    return $this->throwFileArrayClause( $sFile, $sSort, null, null );
  } // end function throwFileArray

  /**
  * Return file in array with max (defined) elements
  * @return array
  * @param string $sFile
  * @param string $sSort
  * @param int    $iPage
  * @param int    $iMax
  */
  function throwFileArrayPages( $sFile = null, $sSort = null, $iPage = null, $iMax = 20 ){
    return $this->throwFileArrayClausePages( $sFile, $sSort, $iPage, $iMax, null, null );
  } // end function throwFileArrayPages

  /**
  * Return file array if defined in parameter function return true
  * @return array
  * @param string $sFile
  * @param string $sSort
  * @param string $sFunction
  * @param mixed  $mFunctionParam
  */
  function throwFileArrayFunction( $sFile = null, $sSort = null, $sFunction, $mFunctionParam = null ){
    if( isset( $sFile ) )
			$this->setFileName( $sFile );
    $this->openFile( 'r' );
    if( $this->throwExtOfFile( $this->fileName ) == 'php' )
      $iStart = 1;
    else
      $iStart = 0;
    $i = 0;
    while( ( $aFile = fgetcsv( $this->rFile, $this->iEol, $this->sSeperator ) ) !== FALSE ){
      if( $i >= $iStart )
        $bReturnFunc = $sFunction( $aFile, $mFunctionParam );
      if( isset( $bReturnFunc ) ){
        $aData[] = $aFile;
      }
      $i++;
    } // end while
    $this->closeFile( );
    if( isset( $aData ) ){
      if( isset( $sSort ) ){
        if( isset( $this->bSortNumeric ) ){
          $sSort( $aData, SORT_NUMERIC );
          $this->bSortNumeric = null;
        }
        else
          $sSort( $aData );
      }
      return $aData;
    }
    else
      return null;
  } // end function throwFileArrayFunction

  /**
  * Return file array if defined in parameter function return true with max (defined) elements
  * @return array
  * @param string $sFile
  * @param string $sSort
  * @param int    $iPage
  * @param int    $iMax
  * @param string $sFunction
  * @param mixed  $mFunctionParam
  */
  function throwFileArrayFunctionPages( $sFile = null, $sSort = null, $iPage = null, $iMax = 20, $sFunction, $mFunctionParam = null ){
    if( isset( $sFile ) )
			$this->setFileName( $sFile );
    $aFile      = file( $this->fileName );
    $iCount     = count( $aFile );
    $iFindPage  = 0;
    $iFindAll   = 0;
    if( isset( $sSort ) ){
      if( isset( $this->bSortNumeric ) ){
        $sSort( $aFile, SORT_NUMERIC );
        $this->bSortNumeric = null;
      }
      else
        $sSort( $aFile );
    }
    if( $this->throwExtOfFile( $this->fileName ) == 'php' )
      $iStart = 1;
    else
      $iStart = 0;
    for( $i = $iStart; $i < $iCount; $i++ ){
      $aExp = explode( '$', $aFile[$i], $this->iExp );
      $bReturnFunc = $sFunction( $aExp, $mFunctionParam );
      if( isset( $bReturnFunc ) ){
        $iFindPage++;
        $iFindAll++;
        
        if( $iFindPage == 1 )
          $aPageStart[] = $i;

        if( isset( $aPageStart[$iPage - 1] ) && !isset( $aPageEnd[$iPage - 1] ) ){
          $aData[] = $aExp;
        }

        if( $iFindPage == $iMax ){
          $aPageEnd[] = $i;
          $iFindPage =  0;
        }
      }
    } // end for
    if( isset( $aData ) ){
      $aData[0]['iFindAll'] = $iFindAll;
      return $aData;
    }
    else
      return null;
  } // end function throwFileArrayFunctionPages

  /**
  * Return file array if data in one column have defined specify value
  * @return array
  * @param string $sFile
  * @param string $sSort
  * @param int    $iPage
  * @param int    $iMax
  * @param int    $iVerifyIndex
  * @param int    $mValue
  */
  function throwFileArrayClausePages( $sFile = null, $sSort = null, $iPage = null, $iMax = 20, $iVerifyIndex, $mValue ){
    if( isset( $sFile ) )
			$this->setFileName( $sFile );
    $aFile      = file( $this->fileName );
    $iCount     = count( $aFile );
    $iFindPage  = 0;
    $iFindAll   = 0;
    if( isset( $sSort ) ){
      if( isset( $this->bSortNumeric ) ){
        $sSort( $aFile, SORT_NUMERIC );
        $this->bSortNumeric = null;
      }
      else
        $sSort( $aFile );
    }
    if( $this->throwExtOfFile( $this->fileName ) == 'php' )
      $iStart = 1;
    else
      $iStart = 0;
    for( $i = $iStart; $i < $iCount; $i++ ){
      $aExp = explode( '$', $aFile[$i], $this->iExp );
      if( !isset( $mValue ) || $aExp[$iVerifyIndex] == $mValue ){
        $iFindPage++;
        $iFindAll++;
        
        if( $iFindPage == 1 )
          $aPageStart[] = $i;

        if( isset( $aPageStart[$iPage - 1] ) && !isset( $aPageEnd[$iPage - 1] ) ){
          $aData[] = $aExp;
        }

        if( $iFindPage == $iMax ){
          $aPageEnd[] = $i;
          $iFindPage =  0;
        }
      }
    } // end for
    if( isset( $aData ) ){
      $aData[0]['iFindAll'] = $iFindAll;
      return $aData;
    }
    else
      return null;
  } // end function throwFileArrayClausePages

  /**
  * Return file array if data in one column have defined specify value
  * @return array
  * @param string $sFile
  * @param string $sSort
  * @param int    $iVerifyIndex
  * @param int    $mValue
  */
  function throwFileArrayClause( $sFile = null, $sSort = null, $iVerifyIndex, $mValue ){
    if( isset( $sFile ) )
			$this->setFileName( $sFile );
    $this->openFile( 'r' );
    if( $this->throwExtOfFile( $this->fileName ) == 'php' )
      $iStart = 1;
    else
      $iStart = 0;
    $i = 0;
    while( ( $aFile = fgetcsv( $this->rFile, $this->iEol, $this->sSeperator ) ) !== FALSE ){
      if( $i >= $iStart && ( !isset( $mValue ) || $aFile[$iVerifyIndex] == $mValue ) ){
        $aData[] = $aFile;
      }
      $i++;
    } // end while
    $this->closeFile( );
    if( isset( $aData ) ){
      if( isset( $sSort ) ){
        if( isset( $this->bSortNumeric ) ){
          $sSort( $aData, SORT_NUMERIC );
          $this->bSortNumeric = null;
        }
        else
          $sSort( $aData );
      }
      return $aData;
    }
    else
      return null;
  } // end function throwFileArrayClause

  /**
  * Return file in array with 2 defined indexes
  * @return array
  * @param string $sFile
  * @param string $sSort
  * @param int    $iIndexFirst - index array'a
  * @param int    $iIndexSecond - index wartosci array'a
  */
  function throwFileArraySmall( $sFile = null, $sSort = null, $iIndexFirst = 0, $iIndexSecond = 1 ){
    if( isset( $sFile ) )
			$this->setFileName( $sFile );
    $this->openFile( 'r' );
    if( $this->throwExtOfFile( $this->fileName ) == 'php' )
      $iStart = 1;
    else
      $iStart = 0;
    $i = 0;
    while( ( $aFile = fgetcsv( $this->rFile, $this->iEol, $this->sSeperator ) ) !== FALSE ){
      if( $i >= $iStart ){
        $aData[$aFile[$iIndexFirst]] = changeTxt( $aFile[$iIndexSecond] );
      }
      $i++;
    } // end while
    $this->closeFile( );
    if( isset( $aData ) ){
      if( isset( $sSort ) ){
        if( isset( $this->bSortNumeric ) ){
          $sSort( $aData, SORT_NUMERIC );
          $this->bSortNumeric = null;
        }
        else
          $sSort( $aData );
      }
      return $aData;
    }
    else
      return null; 
  } // end function throwFileArraySmall

  /**
  * Return one row from file if one column = defined parameter $mValue
  * @return array
  * @param string $sFile
  * @param mixed  $mValue
  * @param int    $iPosition
  */
  function throwData( $sFile = null, $mValue, $iPosition = 0 ){
		if( isset( $sFile ) )
			$this->setFileName( $sFile );	
    $this->openFile( 'r' );
    if( $this->throwExtOfFile( $this->fileName ) == 'php' )
      $iStart = 1;
    else
      $iStart = 0;
    $i = 0;
    while( ( $aFile = fgetcsv( $this->rFile, $this->iEol, $this->sSeperator ) ) !== FALSE ){
      if( $i >= $iStart && $aFile[$iPosition] == $mValue ){
        $aReturn = $aFile;
      }
      $i++;
    } // end while
    $this->closeFile( );
    if( isset( $aReturn ) )
      return $aReturn;
    else
      return null; 
  } // end function throwData

  /**
  * Return file data in HTML select
  * @return string
  * @param string $sFile
  * @param int    $iId
  * @param int    $iVerify
  * @param int    $iValue
  * @param int    $iName
  */
  function throwFileSelect( $sFile = null, $iId, $iVerify = 0, $iValue = 0, $iName = 1 ){
		if( isset( $sFile ) )
			$this->setFileName( $sFile );	
    $this->openFile( 'r' );
    if( $this->throwExtOfFile( $this->fileName ) == 'php' )
      $iStart = 1;
    else
      $iStart = 0;
    $i        = 0;
    $sOption  = null;
    while( ( $aFile = fgetcsv( $this->rFile, $this->iEol, $this->sSeperator ) ) !== FALSE ){
      if( $i >= $iStart ){
        if( isset( $iId ) && $aFile[$iVerify] == $iId )
          $sSelected = 'selected="selected"';
        else
          $sSelected = null;
  
        $sOption .= '<option value="'.$aFile[$iValue].'" '.$sSelected.' >'.$aFile[$iName].'</option>';
      }
      $i++;
    } // end while
    $this->closeFile( );
    return $sOption;  
  } // end function throwDataSelect

  /**
  * Delete data from file
  * @return bool
  * @param string $sFile
  * @param mixed  $mValue
  * @param int    $iPosition
  */
  function deleteInFile( $sFile = null, $mValue, $iPosition = 0 ){
		if( isset( $sFile ) )
			$this->setFileName( $sFile );	
    if( $this->throwExtOfFile( $this->fileName ) == 'php' )
      $iStart = 0;
    else
      $iStart = -1;
    $bFound = null;
    $aFile  = file( $this->fileName );
    $iCount = count( $aFile );
    $this->openFile( 'w' );
    for( $i = 0; $i < $iCount; $i++ ){
      if( $i > $iStart ){
        $aExp = explode( '$', $aFile[$i] );
        if( $aExp[$iPosition] == $mValue ){
          $aFile[$i] = null;
          $bFound = true;
        }
      }
      fwrite( $this->rFile, $aFile[$i] );
    } // end for
		$this->closeFile( );		
		return $bFound;
	} // end function deleteInFile

  /**
  * Change specify data in file
  * @return null
  * @param string $sFile
  * @param mixed  $mValue
  * @param int    $iPosition
  * @param string $sOption
  */
  function changeInFile( $sFile = null, $mValue, $iPosition = 0, $sOption = null ){
    if( isset( $sFile ) )
			$this->setFileName( $sFile );	
		if( isset( $this->aRow ) && is_array( $this->aRow ) )
			$this->sTxt = implode( $this->sSeperator, $this->aRow ).$this->sSeperator;
		else 
			$this->sTxt = $this->sString;
    if( ereg( 'sort', $sOption ) )
      $this->saveData( $sOption, $mValue, $iPosition );
    else
      $this->saveData( null, $mValue, $iPosition );
		$this->closeFile( );
    unset( $this->mData, $this->aRow, $this->sString );
	} // end function changeInFile
};
?>