<?php
/**
* FlatFiles
* @access public
* @version 0.4.1
* @require FileJobs
* @require Trash
*/
final class FlatFiles extends FileJobs
{
protected $sFileName;
private $aFieldsNames;
private $aFieldsSort;
private $aFieldsDefault;
private $aFunctionsNames;
private $aFilesDefNames;
private $rFile;
private $mData;
private $sSeperator = '$';
private $sBreak = "\n";
private $iExp = 30;
private $bLock = null;
private $bLangNameDel = true;
private static $oInstance = null;
public static function getInstance( ){
if( !isset( self::$oInstance ) ){
self::$oInstance = new FlatFiles( );
}
return self::$oInstance;
} // end function getInstance
/**
* Add file lock
* @return void
*/
public function setLock( ){
$this->bLock = true;
} // end function setRow
/**
* Set explode limit
* @return void
* @param array $iExp
*/
public function setExp( $iExp ){
$this->iExp = $iExp;
} // end function setExp
/**
* Set file name
* @return void
* @param string $sFileName
*/
public function setFileName( $sFileName ){
$this->sFileName = $sFileName;
} // end function setFileName
/**
* Open file
* @return int
* @param string $sAttribute
*/
private function openFile( $sAttribute ){
$this->rFile = fopen( $this->sFileName, $sAttribute );
if( isset( $this->bLock ) )
flock( $this->rFile, LOCK_EX );
} // end function openFile
/**
* Close file
* @return void
*/
private function closeFile( ){
if( isset( $this->bLock ) ){
flock( $this->rFile, LOCK_UN );
$this->bLock = null;
}
fclose( $this->rFile );
} // end function closeFile
/**
* Return function name
* @return string
* @param string $sFileName
*/
public function throwFunctionName( $sFileName ){
if( isset( $this->aFunctionsNames[$sFileName] ) )
return $this->aFunctionsNames[$sFileName];
else{
if( isset( $this->bLangNameDel ) && strstr( substr( basename( $sFileName ), 0, 3 ), '_' ) ){
return substr( basename( $this->throwNameOfFile( $sFileName ) ), 3 );
}
else{
return basename( $this->throwNameOfFile( $sFileName ) );
}
}
} // end function throwFunctionName
/**
* Return file definition content
* @return array
* @param string $sFileName
*/
public function getDefFileContent( $sFileName ){
$this->setFileDefVariables( $sFileName );
return Array( 'aFieldsNames' => $this->aFieldsNames[$sFileName], 'aFieldsSort' => $this->aFieldsSort[$sFileName], 'aFieldsDefault' => $this->aFieldsDefault[$sFileName], 'sFunctionName' => $this->aFunctionsNames[$sFileName] );
} // end function getDefFileContent
/**
* Set variables from def file
* @return void
* @param string $sFileName
*/
private function setFileDefVariables( $sFileName ){
if( !isset( $this->aFilesDefNames[$sFileName] ) ){
$aExp = $this->throwNameExtOfFile( $sFileName );
if( isset( $this->bLangNameDel ) && strstr( substr( basename( $aExp[0] ), 0, 3 ), '_' ) ){
$sFile = dirname( $aExp[0] ).'/'.substr( basename( $aExp[0] ), 2 );
$this->aFilesDefNames[$sFileName] = $sFile.'.def'.'.'.$aExp[1];
}
else{
$sFile = $aExp[0];
if( isset( $this->bLangNameDel ) )
$this->aFilesDefNames[$sFileName] = dirname( $aExp[0] ).'/_'.basename( $aExp[0] ).'.def'.'.'.$aExp[1];
else
$this->aFilesDefNames[$sFileName] = $sFile.'.def'.'.'.$aExp[1];
}
$this->aFunctionsNames[$sFileName] = $this->throwFunctionName( $sFileName );
if( is_file( $this->aFilesDefNames[$sFileName] ) ){
include $this->aFilesDefNames[$sFileName];
$this->aFieldsNames[$sFileName] = $aFieldsNames;
if( isset( $aFieldsSort ) )
$this->aFieldsSort[$sFileName] = $aFieldsSort;
else
$this->aFieldsSort[$sFileName] = null;
if( isset( $aFieldsDefault ) )
$this->aFieldsDefault[$sFileName] = $aFieldsDefault;
else
$this->aFieldsDefault[$sFileName] = null;
}
else{
echo 'ERROR - NO FILE <b>'.$this->aFilesDefNames[$sFileName].'</b><br />';
}
}
} // end function setFileDefVariables
/**
* Save data to file
* @return bool
* @param string $sFileName
* @param array $aData
* @param string $sId
* @param string $sSort
*/
public function save( $sFileName, $aData, $sId = null, $sSort = null ){
$this->setFileName( $sFileName );
$this->setFileDefVariables( $this->sFileName );
if( is_file( $this->sFileName ) && is_file( $this->aFilesDefNames[$this->sFileName] ) && is_array( $aData ) ){
$sFunctionName = $this->aFunctionsNames[$this->sFileName];
foreach( $this->aFieldsNames[$this->sFileName] as $sIndex => $iIndex ){
if( isset( $aData[$sIndex] ) ){
if( $sIndex[0] == 'i' ) // if index starts from i letter, then value will have type int
$aData[$sIndex] = (int) $aData[$sIndex];
$aFields[$iIndex] = $aData[$sIndex];
if( isset( $sId ) && $sIndex == $sId ){
$iId = $iIndex;
}
}
else{
if( isset( $this->aFieldsDefault[$this->sFileName] ) && !empty( $this->aFieldsDefault[$this->sFileName][$iIndex] ) ){
$aFields[$iIndex] = $this->aFieldsDefault[$this->sFileName][$iIndex];
}
else
$aFields[$iIndex] = null;
}
} // end foreach
if( isset( $this->aFieldsSort[$this->sFileName] ) && isset( $aFields ) && !empty( $sSort ) && $sSort != 'end' && $sSort != 'top' && function_exists( $sSort ) ){ // if sort variable
$aData = null;
$aFile = file( $this->sFileName );
$iCount = count( $aFile );
if( $this->throwExtOfFile( $this->sFileName ) == 'php' ){
$iStart = 1;
$sSaveBefore = $aFile[0];
}
else{
$iStart = 0;
$sSaveBefore = null;
}
if( $iCount == $iStart ){
$aFile[] = $aFields;
$iCount++;
}
for( $i = $iStart; $i < $iCount; $i++ ){
if( is_array( $aFile[$i] ) ){
$aExp = $aFile[$i];
$bFound = true;
}
else
$aExp = explode( $this->sSeperator, $aFile[$i] );
if( isset( $iId ) && $aFields[$iId] == $aExp[$iId] ){
$aExp = $aFields;
$bFound = true;
}
if( !isset( $bFound ) && $i == $iCount - 1 ){
$aFile[] = $aFields;
$iCount++;
$bFound = true;
}
// $iCount - all indexes count from 1st line from .def file
foreach( $this->aFieldsSort[$this->sFileName] as $iIndex => $sIndex ){
// new array created to sort by sort/rsort function
$iIndex = $this->aFieldsNames[$this->sFileName][$sIndex];
if( !isset( $aExp[$iIndex] ) )
$aExp[$iIndex] = null;
$aData[$i][] = $aExp[$iIndex];
} // end foreach
} // end for
// sorting array
$sSort( $aData );
foreach( $this->aFieldsSort[$this->sFileName] as $iIndex => $sIndex ){
$aDataMap[$this->aFieldsNames[$this->sFileName][$sIndex]] = $iIndex;
} // end for
// save to file
$this->openFile( 'w' );
$iCount = count( $aData );
fwrite( $this->rFile, $sSaveBefore );
for( $i = 0; $i < $iCount; $i++ ){
foreach( $this->aFieldsNames[$this->sFileName] as $sIndex => $iIndex ){
$aSave[] = $aData[$i][$aDataMap[$iIndex]];
}
fwrite( $this->rFile, implode( $this->sSeperator, $aSave ).$this->sSeperator.$this->sBreak );
$aSave = null;
} // end for
$this->closeFile( );
}
else{ // if sort is not defined
if( isset( $iId ) ){ // if id is defined
$aFile = file( $this->sFileName );
$iCount = count( $aFile );
if( $this->throwExtOfFile( $this->sFileName ) == 'php' ){
$iStart = 1;
$sSaveBefore = $aFile[0];
}
else{
$iStart = 0;
$sSaveBefore = null;
}
$this->openFile( 'w' );
fwrite( $this->rFile, $sSaveBefore );
for( $i = $iStart; $i < $iCount; $i++ ){
$aExp = explode( $this->sSeperator, $aFile[$i] );
if( $aFields[$iId] == $aExp[$iId] ){
fwrite( $this->rFile, rtrim( implode( $this->sSeperator, $aFields ) ).$this->sSeperator.$this->sBreak );
}
else{
fwrite( $this->rFile, $aFile[$i] );
}
} // end for
$this->closeFile( );
}
else{
if( $sSort == 'top' ){ // save to top of file
$aFile = file( $this->sFileName );
$iCount = count( $aFile );
if( $this->throwExtOfFile( $this->sFileName ) == 'php' ){
$iStart = 1;
$sSaveBefore = $aFile[0];
}
else{
$iStart = 0;
$sSaveBefore = null;
}
$this->openFile( 'w' );
fwrite( $this->rFile, $sSaveBefore );
fwrite( $this->rFile, rtrim( implode( $this->sSeperator, $aFields ) ).$this->sSeperator.$this->sBreak );
for( $i = $iStart; $i < $iCount; $i++ ){
fwrite( $this->rFile, $aFile[$i] );
} // end for
$this->closeFile( );
}
else{ // save to end of file
$this->openFile( 'a' );
fwrite( $this->rFile, implode( $this->sSeperator, $aFields ).$this->sSeperator.$this->sBreak );
$this->closeFile( );
}
}
}
}
else
return false;
} // end function save
/**
* Return position by name of index
* @return string
* @param string $sFileName
* @param string $sIndex
*/
public function getPositionByIndex( $sFileName, $sIndex ){
$this->setFileDefVariables( $sFileName );
if( isset( $this->aFieldsNames[$sFileName][$sIndex] ) )
return $this->aFieldsNames[$sFileName][$sIndex];
} // end function getPositionByIndex
/**
* Return last id of file
* @return int
* @param string $sFile
* @param string $sIndex
*/
public function throwLastId( $sFile, $sIndex ){
$this->setFileName( $sFile );
$iPosition = $this->getPositionByIndex( $this->sFileName, $sIndex );
if( is_file( $this->sFileName ) && is_numeric( $iPosition ) ){
$aFile = file( $this->sFileName );
$iCount = count( $aFile );
$iMax = 0;
$iStart = $this->throwExtOfFile( $this->sFileName ) == 'php' ? 1 : 0;
for( $i = $iStart; $i < $iCount; $i++ ){
$aExp = explode( $this->sSeperator, $aFile[$i], $this->iExp );
if( $aExp[$iPosition] > $iMax )
$iMax = $aExp[$iPosition];
} // end for
return $iMax;
}
else
return null;
} // end function throwLastId
/**
* Return file in array with 2 defined indexes
* @return array
* @param string $sFile
* @param string $sIndexFirst - index array'a
* @param string $sIndexSecond - index wartosci array'a
*/
public function throwFileArraySmall( $sFile, $sIndexFirst, $sIndexSecond ){
$this->setFileName( $sFile );
$iPosition1 = $this->getPositionByIndex( $this->sFileName, $sIndexFirst );
$iPosition2 = $this->getPositionByIndex( $this->sFileName, $sIndexSecond );
if( is_numeric( $iPosition1 ) && is_numeric( $iPosition2 ) ){
$aFile = file( $this->sFileName );
$iCount = count( $aFile );
$iStart = $this->throwExtOfFile( $this->sFileName ) == 'php' ? 1 : 0;
for( $i = $iStart; $i < $iCount; $i++ ){
$aExp = explode( $this->sSeperator, $aFile[$i], $this->iExp );
$aData[$aExp[$iPosition1]] = $aExp[$iPosition2];
} // end for
if( isset( $aData ) )
return $aData;
}
else
return null;
} // end function throwFileArraySmall
/**
* Return file content
* @return array
* @param string $sFile
* @param mixed $mValue
* @param string $sIndex
*/
public function throwData( $sFile, $mValue, $sIndex ){
$this->setFileName( $sFile );
$iPosition = $this->getPositionByIndex( $this->sFileName, $sIndex );
$sFunction = $this->throwFunctionName( $this->sFileName );
if( is_numeric( $iPosition ) && function_exists( $sFunction ) ){
$aFile = file( $this->sFileName );
$iCount = count( $aFile );
$iStart = $this->throwExtOfFile( $this->sFileName ) == 'php' ? 1 : 0;
for( $i = $iStart; $i < $iCount; $i++ ){
$aExp = explode( $this->sSeperator, $aFile[$i], $this->iExp );
if( $mValue == $aExp[$iPosition] )
return $sFunction( $aExp );
} // end for
}
else{
echo 'ERROR - NO FUNCTION <i>'.$sFunction.'</i> OR INDEX <i>'.$iPosition.'</i> IN file <b>'.$this->sFileName.'</b><br />';
return null;
}
} // end function throwData
/**
* Return array with all files
* @return array
* @param array $aFiles
* @param mixed $mValues
* @param mixed $mIndexes
*/
public function throwDataFromFiles( $aFiles, $mValues, $mIndexes ){
if( is_array( $aFiles ) ){
$iCount = count( $aFiles );
for( $i = 0; $i < $iCount; $i++ ){
$sIndex = is_array( $mIndexes ) ? $mIndexes[$i] : $mIndexes;
$mValue = is_array( $mValues ) ? $mValues[$i] : $mValues;
$aData = $this->throwData( $aFiles[$i], $mValue, $sIndex );
if( isset( $aData ) ){
if( isset( $aReturn ) )
$aReturn = array_merge( $aReturn, $aData );
else
$aReturn = $aData;
}
} // end for
if( isset( $aReturn ) )
return $aReturn;
}
} // end function throwDataFromFiles
/**
* Return file data in HTML select
* @return string
* @param string $sFile
* @param int $iId
* @param string $sIndexVerify
* @param string $sIndexValue
* @param mixed $mIndexName
* @param mixed $mSeparators
*/
public function throwFileSelect( $sFile, $iId, $sIndexVerify, $sIndexValue, $mIndexName, $mSeparators = null ){
$this->setFileName( $sFile );
$iPosition1 = $this->getPositionByIndex( $this->sFileName, $sIndexVerify );
$iPosition2 = $this->getPositionByIndex( $this->sFileName, $sIndexValue );
if( is_array( $mIndexName ) ){
foreach( $mIndexName as $iKey => $sIndexName ){
if( !isset( $mSeparators[$iKey] ) )
$mSeparators[$iKey] = ' ';
$aPostions3[$iKey] = $this->getPositionByIndex( $this->sFileName, $sIndexName );
} // end foreach
}
else{
$iPosition3 = $this->getPositionByIndex( $this->sFileName, $mIndexName );
}
if( is_numeric( $iPosition1 ) && is_numeric( $iPosition2 ) && ( ( isset( $iPosition3 ) && is_numeric( $iPosition3 ) ) || ( isset( $aPostions3 ) && is_array( $aPostions3 ) ) ) ){
$aFile = file( $this->sFileName );
$iCount = count( $aFile );
$iStart = $this->throwExtOfFile( $this->sFileName ) == 'php' ? 1 : 0;
$sOption= null;
for( $i = $iStart; $i < $iCount; $i++ ){
$aExp = explode( $this->sSeperator, $aFile[$i], $this->iExp );
if( isset( $aPostions3 ) ){
$sName = null;
foreach( $aPostions3 as $iKey => $iPosition3 ){
if( isset( $aExp[$iPosition3] ) ){
$sName .= $aExp[$iPosition3].$mSeparators[$iKey];
}
} // end foreach
}
else{
$sName = $aExp[$iPosition3];
}
$sSelected = ( isset( $iId ) && $aExp[$iPosition1] == $iId ) ? ' selected="selected"' : null;
$sOption .= '<option value="'.$aExp[$iPosition2].'"'.$sSelected.'>'.$sName.'</option>';
} // end for
return $sOption;
}
} // end function throwFileSelect
/**
* Delete data from file
* @return bool
* @param string $sFile
* @param mixed $mValue
* @param string $sIndex
*/
public function deleteInFile( $sFile, $mValue, $sIndex ){
$this->setFileName( $sFile );
$iPosition = $this->getPositionByIndex( $this->sFileName, $sIndex );
if( is_file( $this->sFileName ) && is_numeric( $iPosition ) ){
$iStart = $this->throwExtOfFile( $this->sFileName ) == 'php' ? 0 : -1;
$bFound = null;
$aFile = file( $this->sFileName );
$iCount = count( $aFile );
$this->openFile( 'w' );
for( $i = 0; $i < $iCount; $i++ ){
if( $i > $iStart ){
$aExp = explode( '$', $aFile[$i], $this->iExp );
if( is_array( $mValue ) ){
if( isset( $mValue[$aExp[$iPosition]] ) ){
$aFile[$i] = null;
$bFound = true;
}
}
else{
if( $aExp[$iPosition] == $mValue ){
$aFile[$i] = null;
$bFound = true;
}
}
}
fwrite( $this->rFile, $aFile[$i] );
} // end for
$this->closeFile( );
return $bFound;
}
} // end function deleteInFile
/**
* Return file array
* @return array
* @param string $sFile
* @param string $sFunction
* @param mixed $mFunctionParam
* @param int $iPage
* @param int $iMax
* @param string $sSort
* @param bool $bSortNumeric
*/
public function throwFileArray( $sFile, $sFunction = null, $mFunctionParam = null, $iPage = null, $iMax = null, $sSort = null, $bSortNumeric = null ){
$this->setFileName( $sFile );
$sFunctionList = $this->throwFunctionName( $this->sFileName );
$aFile = file( $this->sFileName );
$iStart = $this->throwExtOfFile( $this->sFileName ) == 'php' ? 1 : 0;
$iCount = count( $aFile );
if( !isset( $iMax ) )
$iMax = $iCount - $iStart;
if( !isset( $iPage ) )
$iPage = 1;
$iFindPage = 0;
$iFindAll = 0;
if( isset( $sSort ) ){
if( $iStart == 1 ){
unset( $aFile[0] );
$iStart = 0;
$iCount--;
}
if( isset( $bSortNumeric ) )
$sSort( $aFile, SORT_NUMERIC );
else
$sSort( $aFile );
}
for( $i = $iStart; $i < $iCount; $i++ ){
$aList = $sFunctionList( explode( '$', $aFile[$i], $this->iExp ) );
$bReturn = isset( $sFunction ) ? $sFunction( $aList, $mFunctionParam ) : true;
if( isset( $bReturn ) ){
$iFindPage++;
$iFindAll++;
if( $iFindPage == 1 )
$aPageStart[] = $i;
if( isset( $aPageStart[$iPage - 1] ) && !isset( $aPageEnd[$iPage - 1] ) ){
$aData[] = $aList;
}
if( $iFindPage == $iMax ){
$aPageEnd[] = $i;
$iFindPage = 0;
}
}
} // end for
if( isset( $aData ) ){
$aData[0]['iFindAll'] = $iFindAll;
return $aData;
}
else
return null;
} // end function throwFileArray
/**
* Cache files to variables
* @return void
* @param mixed $mFiles
*/
public function cacheFilesIndexes( $mFiles ){
if( is_array( $mFiles ) ){
foreach( $mFiles as $iKey => $sFile ){
if( is_file( $sFile ) )
$this->setFileDefVariables( $sFile );
}
}
else{
if( is_file( $mFiles ) )
$this->setFileDefVariables( $mFiles );
}
} // end function cacheFilesIndexes
};
?>