Skip to content

Instantly share code, notes, and snippets.

@bor0
Last active January 4, 2024 20:56
Show Gist options
  • Save bor0/e7f43a7f94dcc5179f01273dcf23bd10 to your computer and use it in GitHub Desktop.
Save bor0/e7f43a7f94dcc5179f01273dcf23bd10 to your computer and use it in GitHub Desktop.
IO foldable
<?php
abstract class IO_Foldable {
public function __call( $method, $args ) {
if ( strpos( $method, 'foldable_' ) === 0 ) {
$file = array_shift( $args );
return $this->fold_io( $file, array( $this, substr( $method, 9 ) ), $args );
}
}
protected function fold_io( $file, $foldable, $args = [] ) {
$file = fopen( $file, 'r' );
$ctx = [];
while ( false !== ( $line = fgets( $file ) ) ) {
$tmp_args = array_merge( [ $ctx, $line ], $args );
$ctx_new = call_user_func_array( $foldable, $tmp_args );
if ( false === $ctx_new ) {
break;
}
$ctx = $ctx_new;
}
fclose( $file );
return $ctx;
}
}
class WR_Changelog extends IO_Foldable {
/**
* Changelog release header line (WooCommerce.com pattern).
* Example: 2020-xx-xx - version 1.2.3
*
* @var regexp
*/
private static $pattern1 = '/(?<date>[x|*|0-9]{4}[-|.|_][x|*|0-9]{2}[-|.|_][x|*|0-9]{2})\s-\sversion\s(?<version>[0-9]+.[0-9]+.[0-9]+-?[a-z]*)/i';
/**
* Changelog release header line (WordPress.org pattern).
* Example: = 1.2.3 - 2020-xx-xx =
*
* @var regexp
*/
private static $pattern2 = '/=\s?(?<version>[0-9]+\.[0-9]+\.[0-9]+-?[a-z]*)\s(-\s)?(?<date>[x|*|0-9]{4}[-|\/][x|*|0-9]{2}[-|\/][x|*|0-9]{2})\s?=/i';
/**
* New version to generate changelog for.
*
* @var string
*/
private $version = '';
public function __construct( $version ) {
$this->version = $version;
}
/**
* Remove the prefix section of a changelog entry.
*
* @param string $line Changelog entry.
* @return string Trimmed line.
*/
private function trim_prefix( $line ) {
return ltrim( $line, '*>- ' );
}
public function get_current( $ctx, $line ) {
if ( empty( $ctx ) ) {
$ctx = [ 'start' => false, 'changes' => [] ];
}
$line = rtrim( $line, "\r\n" );
if ( $ctx['start'] ) {
// If we encounter an empty line stop processing.
if ( empty( $line ) ) {
return false;
}
// Add changelog entry.
$ctx['changes'][] = $this->trim_prefix( $line );
return $ctx;
}
// Check for first starting pattern.
if ( preg_match( self::$pattern1, $line, $matches ) && $this->version === $matches['version'] ) {
$ctx['start'] = $line;
}
// Check for second starting pattern.
if ( preg_match( self::$pattern2, $line, $matches ) && $this->version === $matches['version'] ) {
$ctx['start'] = $line;
}
return $ctx;
}
}
$changelog = new WR_Changelog( '1.2.3' );
var_dump( $changelog->foldable_get_current( '/Users/boro/dev/ext/woocommerce-bookings/changelog.txt' ) );
/*
$ php io.php
/Users/boro/Desktop/io.php:103:
array(2) {
'start' =>
string(26) "2014-05-19 - version 1.2.3"
'changes' =>
array(3) {
[0] =>
string(35) "Fix - Backend saving of product ID."
[1] =>
string(48) "Fix - Base cost to include min person type cost."
[2] =>
string(60) "Fix - Custom get_price method for wider plugin compatibility"
}
}
*/
<?php
function fold_io( $file, $foldable ) {
$file = fopen( $file );
$ctx = [];
while ( false !== ( $line = fgets( $file ) ) ) {
$ctx = $foldable( $ctx, $line );
if ( empty( $ctx ) ) {
break;
}
}
fclose( $file );
return $ctx;
}
/**
* Get current changelog entries.
*/
function foldable_get_current( $ctx, $line ) {
if ( empty( $ctx ) ) {
$ctx = [ 'start' => false, 'changes' => [] ];
}
$line = rtrim( $line, "\r\n" );
if ( $ctx['start'] ) {
// If we encounter an empty line stop processing.
if ( empty( $line ) ) {
return [];
}
// Add changelog entry.
$ctx['changes'][] = $this->trim_prefix( $line );
return $ctx;
}
// Check for first starting pattern.
if ( preg_match( self::$pattern1, $line, $matches ) && $this->version === $matches['version'] ) {
$ctx['start'] = $line;
}
// Check for second starting pattern.
if ( preg_match( self::$pattern2, $line, $matches ) && $this->version === $matches['version'] ) {
$ctx['start'] = $line;
}
return $ctx;
}
<?php
/**
* Get current changelog entries.
*/
function get_current() {
$file = fopen( $this->folder . 'changelog.txt', 'r' );
$start = false;
$changes = [];
// Read the changelog line by line.
while ( false !== ( $line = fgets( $file ) ) ) {
$line = rtrim( $line, "\r\n" );
if ( $start ) {
// If we encounter an empty line stop processing.
if ( empty( $line ) ) {
break;
}
// Add changelog entry.
$changes[] = $this->trim_prefix( $line );
continue;
}
// Check for first starting pattern.
if ( preg_match( self::$pattern1, $line, $matches ) && $this->version === $matches['version'] ) {
$start = $line;
}
// Check for second starting pattern.
if ( preg_match( self::$pattern2, $line, $matches ) && $this->version === $matches['version'] ) {
$start = $line;
}
}
fclose( $file );
return [
'start' => $start,
'changes' => $changes,
];
}
@bor0
Copy link
Author

bor0 commented Mar 12, 2020

  • foldable_get_current is pure and testable
  • get_current is not pure and not (easily) testable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment