Cześć,
ostatnio wrzuciłem swój projekt z zadania rekrutacyjnego i wiele się nauczyłem dzięki samym odpowiedziom. Dlatego wrzucam gotowe zadanie z innej rekrutacji, jestem bardzo ciekaw co mógłbym zrobić lepiej. Ogólnie jestem zadowolony z tego co zrobiłem. Ciekaw jestem waszej opinii.
Treść zadania:
Proszę o przygotowanie skryptu linii poleceń (Shell), którego zadaniem będzie konwersja plików JSON na CSV i
CSV na JSON.
Wymagania:
- Nazwa skryptu konwertującego: convert.php
- Ścieżka do konwertowanego pliku powinna być przekazywana jako pierwszy argument skryptu:
./convert.php file.csv
./convert.php file.json - Skonwertowane dane należy wyświetlić na standardowy strumień wyjścia (stdout).
- Komunikaty błędów należy wyświetlać na standardowym strumieniu błędów (stderr).
- Logikę konwertującą należy zaprogramować w klasie Converter.
- Separatorem kolumn w plikach CSV może być przecinek lub średnik. Klasa konwertująca musi wykryć
zastosowany separator.
Informacje dodatkowe - Do zadania dołączone są dwa pliki CSV oraz jeden plik JSON.
- Pliki CSV zakodowane są w UTF-8.
- Pierwszy wiersz pliku CSV to nagłówek z nazwami kolumn.
- Proszę wykonać zadanie w PHP 7.3 lub 7.4.
Kod:
<?php
class Converter {
private $path;
private $data;
private $convertedData = "";
private $extension;
private $convertedExt;
private $allowedExt = ['json','csv'];
function __construct($argv)
{
if(count($argv) > 1){
$this->path = $argv[1];
} else {
?>
This is a command line PHP script with one option.
Usage:
<?php echo $argv[0]; ?> <path>
<path> Path to file you would
like to convert - may be the json
or csv file.
<?php
}
}
public function fileValidator($path)
{
if(file_exists($path)){
$this->extension = pathinfo($path, PATHINFO_EXTENSION);
if(in_array($this->extension, $this->allowedExt)){
if(file_get_contents($path)){
$this->data = file_get_contents($path);
return 1;
} else {
fwrite(STDERR, "the file is empty.");
}
} else {
fwrite(STDERR, "File extension not allowed.");
}
} else {
fwrite(STDERR, "file not found.");
}
return 0;
}
public function saveFile(){
if( $this->convertedData ){
$newFile = pathinfo($this->path, PATHINFO_FILENAME)."-".$this->convertedExt.".".$this->convertedExt;
file_put_contents($newFile, $this->convertedData);
echo "\nThe data has been saved to a file named ".$newFile."\n";
} else {
fwrite(STDERR, "First use the convert function. the file was not saved.\n");
}
}
public function json2csv()
{
if( json_decode($this->data, true) ){
$jsonDecoded = json_decode($this->data, true);
$csv = fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+'); // max size of the csv file: 5MB
// find all headers
$headers = [];
foreach($jsonDecoded as $row){
$keysInRow = array_keys($row);
foreach($keysInRow as $keyId=>$key){
if(!in_array($key,$headers)){ // check if there is no such an element in the array
if($keyId === 0){ // if this is first element
$headers[] = $key; // just add this element
} else { // else add the item in the right place
array_splice( $headers, $keyId--, 0, $key );
}
}
}
}
// set the header line
$lastHeader = count($headers); // count the headers and set iterator
$i = 0; // just to avoid giving a comma in the last element
foreach($headers as $header){
$i++;
$this->convertedData .= $header;
if($i != $lastHeader){
$this->convertedData .= ',';
}
}
$this->convertedData .= "\n";
// convert data to csv
foreach($jsonDecoded as $row){
$i = 0;
foreach($headers as $header){
$i++;
if(isset($row[$header])){ // if is set data for this header in this row
$this->convertedData .= $row[$header];
}
if($i != $lastHeader){
$this->convertedData .= ",";
}
}
$this->convertedData .= "\n";
}
$this->convertedExt .= "csv";
} else {
fwrite(STDERR, "Wrong file structure.");
}
}
public function csv2json()
{
$file = fopen($this->path, 'r');
// determine the division sign
if(substr_count($this->data, ',') > substr_count($this->data, ';')){
$dist = ',';
} else {
$dist = ';';
}
// get headers
$keys = fgetcsv($file,"1024",$dist);
// eliminate the bom appearing at the beginning of the file
$keys[0] = preg_replace('/^[\pZ\p{Cc}\x{feff}]+|[\pZ\p{Cc}\x{feff}]+$/ux','',$keys[0]);
$json = array();
while ($row = fgetcsv($file,"1024",$dist)) { // set the each element from row
$json[] = array_combine($keys, $row); // key from keys array
}
// encode array to json
$this->convertedData = json_encode($json, JSON_UNESCAPED_UNICODE ); // fix the utf-8 encoding
$this->convertedExt .= "json";
}
public function convert()
{
if($this->fileValidator($this->path)){
if($this->extension === "json"){
echo "converting json to csv...\n";
$this->json2csv();
echo $this->convertedData;
} else if( $this->extension === "csv"){
echo "converting csv to json...\n";
$this->csv2json();
var_dump($this->convertedData);
} else {
fwrite(STDERR, "Something went wrong.");
}
} else {
return 0;
}
}
}
$converter = new Converter($argv);
$converter->convert();
$converter->saveFile();
?>