move from mirzaev/repression
This commit is contained in:
parent
a24038adfb
commit
fb5738c4b0
|
@ -0,0 +1 @@
|
|||
vendor
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "mirzaev/csv",
|
||||
"description": "Lightweight library for creating CSV databases",
|
||||
"homepage": "https://git.mirzaev.sexy/mirzaev/csv",
|
||||
"type": "library",
|
||||
"keywords": [
|
||||
"csv",
|
||||
"database"
|
||||
],
|
||||
"readme": "README.md",
|
||||
"license": "WTFPL",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Arsen Mirzaev Tatyano-Muradovich",
|
||||
"email": "arsen@mirzaev.sexy",
|
||||
"homepage": "https://mirzaev.sexy",
|
||||
"role": "Programmer"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"email": "arsen@mirzaev.sexy",
|
||||
"wiki": "https://git.mirzaev.sexy/mirzaev/csv/wiki",
|
||||
"issues": "https://git.mirzaev.sexy/mirzaev/csv/issues"
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"require": {
|
||||
"php": "^8.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"mirzaev\\csv\\": "mirzaev/csv/system/"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "70ef8045ba581d96d3a68483b6031a33",
|
||||
"packages": [],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": "^8.4"
|
||||
},
|
||||
"platform-dev": {},
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\csv\interfaces;
|
||||
|
||||
// Files of the project
|
||||
use mirzaev\csv\traits\csv as csv_trait;
|
||||
|
||||
/**
|
||||
* CSV
|
||||
*
|
||||
* Comma-Separated Values by RFC 4180
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc4180
|
||||
*
|
||||
* @used-by csv_trait
|
||||
* @package mirzaev\csv\interfaces
|
||||
*
|
||||
* @var string FILE Path to the database file
|
||||
*
|
||||
* @method void static write() Write to the database file
|
||||
* @method array|null static read() Read from the database file
|
||||
* @method string|false static serialize() Preparing data for writing to the database
|
||||
* @method array|false static deserialize() Preparing data from the database to processing
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
interface csv
|
||||
{
|
||||
/**
|
||||
* File
|
||||
*
|
||||
* Path directories to the file will not be created automatically to avoid
|
||||
* checking the existence of all directories on every read or write operation.
|
||||
*
|
||||
* @var string FILE Path to the database file
|
||||
*/
|
||||
public const string FILE = 'database.csv';
|
||||
|
||||
/**
|
||||
* Write
|
||||
*
|
||||
* Write to the database file
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function write(): void;
|
||||
|
||||
/**
|
||||
* Read
|
||||
*
|
||||
* Read from the start of the database file
|
||||
*
|
||||
* @param int $rows Amount of rows for reading
|
||||
*
|
||||
* @return array|null Readed records
|
||||
*/
|
||||
public static function read(int $rows = 1): ?array;
|
||||
|
||||
/**
|
||||
* Last
|
||||
*
|
||||
* Read from the end of the database file
|
||||
*
|
||||
* @param int $rows Amount of rows for reading
|
||||
*
|
||||
* @return array|null Readed records
|
||||
*/
|
||||
public static function last(int $rows = 1): ?array;
|
||||
|
||||
/**
|
||||
* Serialize
|
||||
*
|
||||
* Preparing data for writing to the database
|
||||
*
|
||||
* @param array $parameters Values for serializing
|
||||
*
|
||||
* @return string|false Serialized data
|
||||
*/
|
||||
public static function serialize(array $parameters): string|false;
|
||||
|
||||
/**
|
||||
* Deserialize
|
||||
*
|
||||
* Preparing data from the database to processing
|
||||
*
|
||||
* @param string $row Record for deserializing
|
||||
*
|
||||
* @return array|false Serialized data
|
||||
*/
|
||||
public static function deserialize(string $row): array|false;
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\csv\traits;
|
||||
|
||||
// Files of the project
|
||||
use mirzaev\csv\interfaces\csv as csv_interface;
|
||||
|
||||
// Built-in libraries
|
||||
use exception;
|
||||
|
||||
/**
|
||||
* CSV
|
||||
*
|
||||
* Comma-Separated Values by RFC 4180
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc4180
|
||||
*
|
||||
* @uses csv_interface
|
||||
* @package mirzaev\csv\traits
|
||||
*
|
||||
* @method static array|null read(int $rows, array &$errors) Read from the start of the database file
|
||||
* @method static string|false serialize(array $parameters, bool $created) Preparing data for writing to the database
|
||||
* @method static array|false deserialize(string $row) Preparing data from the database to processing
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
trait csv
|
||||
{
|
||||
/**
|
||||
* Read
|
||||
*
|
||||
* Read from the start of the database file
|
||||
*
|
||||
* @param int $rows Amount of rows for reading
|
||||
* @param array &$errors Buffer of errors
|
||||
*
|
||||
* @return array|null Readed records
|
||||
*/
|
||||
public static function read(int $rows = 0, &$errors = []): ?array
|
||||
{
|
||||
try {
|
||||
// Initializing the buffer of readed records
|
||||
$records = [];
|
||||
|
||||
// Opening the file with views records
|
||||
$file = fopen(static::FILE, 'c+');
|
||||
|
||||
while (--$rows >= 0 && ($row = fgets($file, 4096)) !== false) {
|
||||
// Iterating over rows (records)
|
||||
|
||||
// Deserealizing record
|
||||
$deserialized = static::deserialize($row);
|
||||
|
||||
if ($deserialized) {
|
||||
// Deserialized record
|
||||
|
||||
// Writing to the buffer of readed records
|
||||
$records[] = $deserialized;
|
||||
}
|
||||
}
|
||||
|
||||
// Closing file with views records
|
||||
fclose($file);
|
||||
|
||||
// Exit (success)
|
||||
return $records;
|
||||
} catch (exception $e) {
|
||||
// Write to the buffer of errors
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
// Exit (fail)
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize
|
||||
*
|
||||
* Preparing data for writing to the database
|
||||
*
|
||||
* @param array $parameters Values for serializing
|
||||
* @param bool $created Add date of creating at the end?
|
||||
*
|
||||
* @return string|false Serialized data
|
||||
*/
|
||||
public static function serialize(array $parameters, bool $created = false): string|false
|
||||
{
|
||||
// Declaring the buffer of serialized values
|
||||
$serialized = '';
|
||||
|
||||
// Sanitizing values
|
||||
foreach ($parameters as $value) $serialized .= ',' . preg_replace('/(?<=[^^])"(?=[^$])/', '""', preg_replace('/(?<=[^^]),(?=[^$])/', '\,', $value ?? ''));
|
||||
|
||||
// Writing date of creating to the buffer of serialized values
|
||||
if ($created) $serialized .= ',' . time();
|
||||
|
||||
// Trimming excess first comma in the buffer of serialized values
|
||||
$serialized = mb_substr($serialized, 1, mb_strlen($serialized));
|
||||
|
||||
// Exit (success/fail)
|
||||
return empty($serialized) ? false : $serialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize
|
||||
*
|
||||
* Preparing data from the database to processing
|
||||
*
|
||||
* @param string $row Record for deserializing
|
||||
*
|
||||
* @return array|false Deserialized data
|
||||
*/
|
||||
public static function deserialize(string $row): array|false
|
||||
{
|
||||
// Separating row by commas
|
||||
preg_match_all('/(?:^|,)(?=[^"]|(")?)"?((?(1)[^"]*|[^,"]*))"?(?=,|$)/', $row, $matches);
|
||||
|
||||
// Converting double quotes to single quotes
|
||||
foreach ($matches[2] as &$match)
|
||||
if (empty($match = preg_replace('/[\n\r]/', '', preg_replace('/""/', '"', preg_replace('/\\\,/', ',', trim((string) $match, '"'))))))
|
||||
$match = null;
|
||||
|
||||
// Exit (success/fail)
|
||||
return empty($matches[2]) ? false : $matches[2];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\repression\models\traits;
|
||||
|
||||
// Built-in libraries
|
||||
use Exception as exception,
|
||||
Generator as generator;
|
||||
|
||||
/**
|
||||
* File
|
||||
*
|
||||
* @package mirzaev\csv\traits
|
||||
*
|
||||
* @method static generator|null|false read($file, int $offset, int $rows, int $position, int $step, array &$errors) Read the file
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
trait file
|
||||
{
|
||||
/**
|
||||
* Read
|
||||
*
|
||||
* Read the file
|
||||
*
|
||||
* @param resource $file Pointer to the file (fopen())
|
||||
* @param int $offset Offset of rows for start reading
|
||||
* @param int $rows Amount of rows for reading
|
||||
* @param int $position Initial cursor position on a row
|
||||
* @param int $step Reading step
|
||||
* @param array &$errors Buffer of errors
|
||||
*
|
||||
* @return generator|null|false
|
||||
*/
|
||||
private static function read($file, int $offset = 0, int $rows = 10, int $position = 0, int $step = 1, array &$errors = []): generator|null|false
|
||||
{
|
||||
try {
|
||||
while ($offset-- > 0) {
|
||||
do {
|
||||
// Iterate over symbols of the row
|
||||
|
||||
// The end (or the beginning) of the file reached (success)
|
||||
if (feof($file)) break;
|
||||
|
||||
// Moving the cursor to next position on the row
|
||||
fseek($file, $position += $step, SEEK_END);
|
||||
|
||||
// Reading a character of the row
|
||||
$character = fgetc($file);
|
||||
|
||||
// Is the character a carriage return? (end or start of the row)
|
||||
} while ($character !== PHP_EOL);
|
||||
}
|
||||
|
||||
while ($rows-- > 0) {
|
||||
// Reading rows
|
||||
|
||||
// Initializing of the buffer of row
|
||||
$row = '';
|
||||
|
||||
// Initializing the character buffer to generate $row
|
||||
$character = '';
|
||||
|
||||
do {
|
||||
// Iterate over symbols of the row
|
||||
|
||||
// The end (or the beginning) of the file reached (success)
|
||||
if (feof($file)) break;
|
||||
|
||||
// Building the row
|
||||
$row = $step > 0 ? $row . $character : $character . $row;
|
||||
|
||||
// Moving the cursor to next position on the row
|
||||
fseek($file, $position += $step, SEEK_END);
|
||||
|
||||
// Reading a character of the row
|
||||
$character = fgetc($file);
|
||||
|
||||
// Is the character a carriage return? (end or start of the row)
|
||||
} while ($character !== PHP_EOL);
|
||||
|
||||
// Exit (success)
|
||||
yield empty($row) ? null : $row;
|
||||
}
|
||||
|
||||
// Exit (success)
|
||||
return null;
|
||||
} catch (exception $e) {
|
||||
// Write to the buffer of errors
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
// Exit (fail)
|
||||
return false;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue