Skip to content

Instantly share code, notes, and snippets.

@Adrian0350
Last active April 4, 2017 18:52
Show Gist options
  • Save Adrian0350/9d8715cb9a934f79ea1a2b5861a7af15 to your computer and use it in GitHub Desktop.
Save Adrian0350/9d8715cb9a934f79ea1a2b5861a7af15 to your computer and use it in GitHub Desktop.
<?php
namespace Utility;
/**
* This class replaces CRLF (Windows) endlines
* with LF (Unix) endlines.
*/
class CSVCleaner
{
/**
* General constants for class.
* They pretty much explay themselves.
*/
const MAX_STREAM_SIZE = 8192;
const CRLF_CR = array("\r\n", "\r");
const LF = "\n";
/**
* Default file permissions
* to apply after modifying data.
* Everything for owner, read and execute for others.
* In Octal value.
*/
const PERMISSIONS = array(
'rw_owner' => 0600,
'rw_owner_r_all' => 0644,
'rwx_owner_rx_group' => 0750,
'rwx_owner_rx_all' => 0755
);
/**
* Replaces CRLF with LF.
*
* @param string $file The filepath.
* @return bool Wheather the data in file was modified.
*/
public static function process($file)
{
if (!self::isFileWrittable($file))
{
return false;
}
$file_size = filesize($file);
$handle = fopen($file, 'rb');
if ($file_size > self::MAX_STREAM_SIZE)
{
$tmp_file = $this->createTempDir();
// Loops as long as the reading by MAX_STREAM_SIZE chunk finishes.
while ($processed_data = self::CRLF2LF(fread($handle, self::MAX_STREAM_SIZE)))
{
file_put_contents($tmp_file, $processed_data, LOCK_EX | FILE_APPEND);
}
fclose($handle);
if (!self::moveFile($tmp_file, $file) && self::applyPermissions($file, 0755))
{
return false;
}
}
else
{
// Process data and then save it or return false.
if (!$processed_data = self::CRLF2LF(fread($handle, $file_size)))
{
return false;
}
fclose($handle);
if (!file_put_contents($file, $processed_data) && self::applyPermissions($file, 0755))
{
return false;
}
}
return true;
}
/**
* A function to know if a given filepath
* is indeed a file or a directory, and
* case being a file, wheather it is writtable or not.
*
* @param string $file The filepath.
* @return bool Wheather is writtable or not.
*/
public static function isFileWrittable($file = '')
{
return !is_dir($file) || file_exists($file) && is_writable($file);
}
/**
* Creates a temporary directory/file name
* using the system's tmp dir.
*
* @return string The directory/file name.
*/
public function createTempDir()
{
return tempnam(sys_get_temp_dir(), time());
}
/**
* Moves a file (filepath) from source -> destination.
*
* @param string $source The source path.
* @param string $destinatino The destination path.
* @return bool
*/
public static function moveFile($source, $destination)
{
return rename($source, $destination);
}
/**
* Replaces CRLF (\r\n) line return with LF (\n).
*
* @param string $data The data to process.
* @return mixed
*/
private static function CRLF2LF($data)
{
if (!$data = str_replace(self::CRLF_CR, self::LF, $data))
{
return false;
}
return self::applyEncoding($data);
}
/**
* Applies given permissions.
*
* @param string $file The filepath.
* @param string $permission The permission to apply.
* @return bool Wheather it was applied or not.
*/
public static function applyPermissions($file, $permission = 0750)
{
if (!in_array($permission, self::PERMISSIONS))
{
return false;
}
return chmod($file, $permission);
}
/**
* Converts data to UTF-8.
* · Reference: http://php.net/manual/en/function.utf8-encode.php#102382
*
* @param mixed $data The data to encode.
* @param string $encoding The encoding to use.
* @return mixed $data The encoded data or false.
*/
private static function applyEncoding($data, $encoding = 'UTF-8')
{
if (!mb_check_encoding($data, $encoding))
{
$data = mb_convert_encoding($data, $encoding);
if (!mb_check_encoding($data, $encoding))
{
return false;
}
}
return $data;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment