silverstripe-framework/thirdparty/php-peg/PHPBuilder.php

128 lines
3.0 KiB
PHP

<?php
class PHPBuilder {
static function build () {
return new PHPBuilder() ;
}
function __construct() {
$this->lines = array() ;
}
function l() {
foreach ( func_get_args() as $lines ) {
if ( !$lines ) continue ;
if ( is_string( $lines ) ) $lines = preg_split( '/\r\n|\r|\n/', $lines ?? '' ) ;
if ( !$lines ) continue ;
if ( $lines instanceof PHPBuilder ) $lines = $lines->lines ;
else $lines = array_map( 'ltrim', $lines ?? [] ) ;
if ( !$lines ) continue ;
$this->lines = array_merge( $this->lines, $lines ) ;
}
return $this ;
}
function b() {
$args = func_get_args() ;
$entry = array_shift( $args ) ;
$block = new PHPBuilder() ;
call_user_func_array( array( $block, 'l' ), $args ?? [] ) ;
$this->lines[] = array( $entry, $block->lines ) ;
return $this ;
}
function replace( $replacements, &$array = NULL ) {
if ( $array === NULL ) {
unset( $array ) ;
$array =& $this->lines ;
}
$i = 0 ;
while ( $i < count( $array ?? [] ) ) {
/* Recurse into blocks */
if ( is_array( $array[$i] ) ) {
$this->replace( $replacements, $array[$i][1] ) ;
if ( count( $array[$i][1] ?? [] ) == 0 ) {
$nextelse = isset( $array[$i+1] ) && is_array( $array[$i+1] ) && preg_match( '/^\s*else\s*$/i', $array[$i+1][0] ?? '' ) ;
$delete = preg_match( '/^\s*else\s*$/i', $array[$i][0] ?? '' ) ;
$delete = $delete || ( preg_match( '/^\s*if\s*\(/i', $array[$i][0] ?? '' ) && !$nextelse ) ;
if ( $delete ) {
// Is this always safe? Not if the expression has side-effects.
// print "/* REMOVING EMPTY BLOCK: " . $array[$i][0] . "*/\n" ;
array_splice( $array, $i ?? 0, 1 ) ;
continue ;
}
}
}
/* Handle replacing lines with NULL to remove, or string, array of strings or PHPBuilder to replace */
else {
if ( array_key_exists( $array[$i], $replacements ?? [] ) ) {
$rep = $replacements[$array[$i]] ;
if ( $rep === NULL ) {
array_splice( $array, $i ?? 0, 1 ) ;
continue ;
}
if ( is_string( $rep ) ) {
$array[$i] = $rep ;
$i++ ;
continue ;
}
if ( $rep instanceof PHPBuilder ) $rep = $rep->lines ;
if ( is_array( $rep ) ) {
array_splice( $array, $i ?? 0, 1, $rep ) ; $i += count( $rep ?? [] ) + 1 ;
continue ;
}
throw 'Unknown type passed to PHPBuilder#replace' ;
}
}
$i++ ;
}
return $this ;
}
function render( $array = NULL, $indent = "" ) {
if ( $array === NULL ) $array = $this->lines ;
$out = array() ;
foreach( $array as $line ) {
if ( is_array( $line ) ) {
list( $entry, $block ) = $line ;
$str = $this->render( $block, $indent . "\t" ) ;
if ( strlen( $str ?? '' ) < 40 ) {
$out[] = $indent . $entry . ' { ' . ltrim( $str ?? '' ) . ' }' ;
}
else {
$out[] = $indent . $entry . ' {' ;
$out[] = $str ;
$out[] = $indent . '}' ;
}
}
else {
$out[] = $indent . $line ;
}
}
return implode( PHP_EOL, $out ) ;
}
}