-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit c137073
Showing
52 changed files
with
2,039 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
root = true | ||
|
||
[*] | ||
end_of-line = lf | ||
charset = utf-8 | ||
|
||
[Makefile] | ||
indent_style = tab | ||
|
||
[*.php] | ||
indent_style = tab |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/csvreader.php | ||
/vendor/ | ||
*~ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
PHP ?= php | ||
|
||
SRC_DIR = src | ||
TESTS_DIR = tests | ||
|
||
all: csvreader.php | ||
|
||
csvreader.php: .FORCE | ||
$(PHP) compile.php $(SRC_DIR)/CSVReader.php >$@ | ||
|
||
test: .FORCE | ||
@if test -n '$(PHPUNIT)'; then set -- $(PHPUNIT); elif test -x vendor/bin/phpunit; then set -- vendor/bin/phpunit; else set -- phpunit; fi; set -- "$$@" --test-suffix .php -vv $(TESTS_DIR); echo "$$@"; "$$@" | ||
|
||
sast: .FORCE | ||
@if test -n '$(PHPSTAN)'; then set -- $(PHPSTAN); elif test -x vendor/bin/phpstan; then set -- vendor/bin/phpstan; else set -- phpstan; fi; set -- "$$@" analyse --no-progress --level=8 $(SRC_DIR); echo "$$@"; "$$@" | ||
|
||
|
||
.FORCE: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# php-csvreader | ||
|
||
This PHP library is an opinionated wrapper around PHP's `fgetcsv()` function | ||
trying to be suitable for guessing (column and row) separators and file encoding | ||
as generated by typical spreadsheet applications (looking at you, Excel). | ||
The heuristics used to guess the encoding detects Unicode encodings correctly. | ||
For legacy code pages, Western European encodings are detected. | ||
|
||
Using this library for non-commercial or free software projects is permissible in accordance with the [GNU General Public License (version 3 or later)](https://www.gnu.org/licenses/gpl-3.0.en.html). | ||
|
||
|
||
## Installation | ||
|
||
### Classic | ||
|
||
The whole library can be compiled into a single PHP file which can be `require`d | ||
from any PHP module: | ||
|
||
```console | ||
$ make | ||
$ php <<EOF | ||
<?php | ||
require 'csvreader.php'; | ||
|
||
// ... | ||
EOF | ||
``` | ||
|
||
|
||
### Composer | ||
|
||
In your project's `composer.json` add the following configuration options and | ||
run `composer install`: | ||
|
||
```json | ||
{ | ||
"repositories": [ | ||
{ | ||
"type": "github", | ||
"url": "https://github.com/riiengineering/php-csvreader" | ||
} | ||
], | ||
"require": { | ||
"riiengineering/php-csvreader": "dev-main" | ||
} | ||
} | ||
``` | ||
|
||
|
||
## Usage | ||
|
||
```php | ||
<?php | ||
require_once 'csvreader.php'; /* if using the classic method */ | ||
require_once 'vendor/autoload.php'; /* if using composer */ | ||
|
||
$reader = new \riiengineering\csvreader\CSVReader( | ||
$file, | ||
array( | ||
'id', | ||
'product', | ||
'currency', | ||
'price', | ||
), | ||
array( | ||
'separator' => ';', | ||
'encoding' => 'AUTO', | ||
'line-separator' => 'AUTO', | ||
)); | ||
|
||
foreach ($reader as $row) { | ||
var_dump($row) . PHP_EOL; | ||
} | ||
``` | ||
|
||
----- | ||
[](//www.riiengineering.ch) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
#!/usr/bin/env php | ||
<?php | ||
|
||
$php_header_ended = FALSE; | ||
$php_declares = array(); | ||
$php_includes = array(); | ||
|
||
function fatal(string $s): void { | ||
fwrite(STDERR, $s); | ||
exit(1); | ||
} | ||
|
||
function php_to_path(string $code, string $file): string { | ||
# NOTE: this function only does some very very basic PHP parsing that should | ||
# be good enough for the average include/require call. | ||
|
||
if (FALSE !== strpos($code, '__DIR__')) { | ||
$code = preg_replace( | ||
'/(^|[ \t]*\.|[a-z_]*\()[ \t]*__DIR__[ \t]*(\.[ \t]*|\)|$)/', | ||
'$1\''.dirname($file).'\'$2', | ||
$code); | ||
} | ||
|
||
if (FALSE !== strpos($code, '__FILE__')) { | ||
$code = preg_replace( | ||
'/(^|[ \t]*\.|[a-z_]*\()[ \t]*__FILE__[ \t]*(\.[ \t]*|\)|$)/', | ||
'$1\''.$file.'\'$2', | ||
$code); | ||
} | ||
|
||
return eval("return(${code});"); | ||
} | ||
|
||
function php_declare(string $k, string $v): void { | ||
global $php_declares, $php_header_ended; | ||
|
||
if (array_key_exists($k, $php_declares)) { | ||
if ($v === $php_declares[$k]) { | ||
return; | ||
} else { | ||
fatal("${k} is already declared with a different value\n"); | ||
} | ||
} | ||
if ($php_header_ended) { | ||
fatal("declare too late\n"); | ||
} | ||
|
||
$php_declares[$k] = $v; | ||
printf("declare(%s=%s);\n", $k, $v); | ||
} | ||
|
||
function process_file(string $filename): void { | ||
global $php_header_ended, $php_includes; | ||
|
||
array_push($php_includes, realpath($filename)); | ||
|
||
$fh = fopen($filename, 'r'); | ||
if (!$fh) { | ||
fatal("failed to process ${filename}\n"); | ||
} | ||
|
||
$php = FALSE; | ||
$ns = ''; | ||
$nsopen = 0; | ||
|
||
// echo "// file:${filename}\n"; | ||
|
||
while (FALSE !== ($line = fgets($fh))) { | ||
$line = rtrim($line, "\n"); | ||
|
||
if (!$php) { | ||
if (preg_match('/<\?php/', $line)) { | ||
$php = TRUE; | ||
$line = preg_replace('/^.*?<\?php/', '', $line); | ||
} else { | ||
continue; | ||
} | ||
} | ||
|
||
if (preg_match('/\?>/', $line)) { | ||
fatal("mixed source detected\n"); | ||
} | ||
|
||
if (preg_match('/^\s*declare\s*\(/', $line)) { | ||
while (preg_match('/^\s*declare\s*\((.*?)\)\s*;\s*/', $line, $matches)) { | ||
call_user_func_array( | ||
'php_declare', | ||
preg_split('/=/', $matches[1], 2)); | ||
$line = substr($line, strlen($matches[0])); | ||
} | ||
} | ||
|
||
$php_header_ended = TRUE; | ||
|
||
if (preg_match('/namespace\s+([A-Za-z0-9\\\\]+)\s*([;{])\s*/', $line, $matches)) { | ||
for (; 0 < $nsopen; --$nsopen) echo "}\n"; | ||
|
||
if (';' === $matches[2]) { | ||
$line = substr($line, strlen($matches[0])); | ||
$ns = $matches[1]; | ||
} else { | ||
$ns = NULL; | ||
} | ||
} | ||
|
||
if (preg_match('/^\s*((?:include|require)(?:_once)?)\s*(\(.*\)|.*)\s*;\s*/', $line, $matches)) { | ||
$path = $matches[2]; | ||
if ('(' === $path[0] && ')' === $path[-1]) $path = substr($path, 1, strlen($path)-2); | ||
|
||
$path = php_to_path($path, $filename); | ||
|
||
if ('_once' !== substr($matches[1], -4) || !in_array($path, $php_includes)) { | ||
if (file_exists($path)) { | ||
for (; 0 < $nsopen; --$nsopen) echo "}\n"; | ||
process_file($path); | ||
} else { | ||
fwrite(STDERR, "${path}: file to include not found\n"); | ||
if (0 === strpos($matches[1], 'require')) { | ||
exit(1); | ||
} | ||
} | ||
} | ||
|
||
$line = substr($line, strlen($matches[0])); | ||
} | ||
|
||
if (trim($line)) { | ||
if (!$nsopen && !is_null($ns)) { | ||
echo $ns ? "namespace ${ns} {\n" : "namespace {\n"; | ||
++$nsopen; | ||
} | ||
echo $line."\n"; | ||
} | ||
} | ||
|
||
for (; 0 < $nsopen; --$nsopen) echo "}\n"; | ||
|
||
// echo "// endf:${filename}\n"; | ||
|
||
fclose($fh); | ||
} | ||
|
||
function main(array $argv): int { | ||
echo "<?php\n"; | ||
|
||
array_shift($argv); // the compiler script itself | ||
foreach ($argv as $arg) { | ||
process_file($arg); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
exit(main($argv)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"name": "riiengineering/csvreader", | ||
"description": "Opinionated CSV reader library tuned to the specifics of spreadsheet applications", | ||
"type": "library", | ||
"readme": "README.md", | ||
"license": "GPL-3.0-or-later", | ||
"authors": [ | ||
{ | ||
"name": "Dennis Camera", | ||
"email": "dennis.camera@riiengineering.ch", | ||
"homepage": "http://www.riiengineering.ch", | ||
"role": "developer" | ||
} | ||
], | ||
"require": { | ||
"php": ">=7.4" | ||
}, | ||
"require-dev": { | ||
"phpunit/phpunit": "*", | ||
"phpstan/phpstan": "*" | ||
}, | ||
"autoload": { | ||
"classmap": [ | ||
"src/CSVReader.php" | ||
] | ||
} | ||
} |
Oops, something went wrong.