Skip to content

Instantly share code, notes, and snippets.

@earth3300
Last active September 26, 2019 15:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save earth3300/78bcdff46e6891caff28ffd6c020212c to your computer and use it in GitHub Desktop.
Save earth3300/78bcdff46e6891caff28ffd6c020212c to your computer and use it in GitHub Desktop.
Converts a CSS file or files to an array and saves as a PHP file or files.
<?php
/**
* EC01 Converts CSS to a PHP Data Array
*
* Converts valid CSS to a PHP data array and saves as a file.
*
* @package Earth3300\EC01
* @since 1.0.0
* @author Clarence J. Bos <cbos@tnoep.ca>
* @copyright Copyright (c) 2018, Clarence J. Bos
* @license https://www.gnu.org/licenses/gpl-3.0.en.html GPL v3.0
* @link https://gist.github.com/earth3300/78bcdff46e6891caff28ffd6c020212c
*
* File: printer.css-to-dat.php
* Created: 2019-09-19
* Updated: 2019-09-23
* Time: 19:56 EDT
* ID: ENG-ON-001
*/
namespace Earth3300\EC01;
if( ! defined( 'NDA' ) )
{
define('NDA',true);
}
/**
* Prints a CSS file.
*/
class CssPrinter
{
/** @var array Default options. */
protected $opts = [
// Development Status.
'dev' => 0,
'dev0' => 0,
'dev1' => 0,
'dev2' => 0,
'dev3' => 0,
'dev4' => 0,
'this' => [
'file' => 'printer.css-to-dat.php',
'title' => 'EC01 CSS to Data Printer',
'date' => [
'created' => '2019-09-19',
],
],
'page' => [
'title' => 'EC01 CSS to Data Printed',
],
'dir' => [
'input' => '/0/t/css/src',
'output' => '/0/t/css/dat',
],
'file' => [
'overwrite' => 1,
],
'files' => [
'exclude' => [
'00-header.css',
],
],
'max' => [
'len' => 3000000, // Bytes
'files' => 1,
],
'write' => [
'root' => 0,
],
'message' => [
'na' => 'Not available.',
'write' => [
'denied' => 'Write permission denied.' ,
'success' => 'Write operation succeeded.',
'failure' => 'Write operation failed.',
],
],
];
function __construct()
{
}
/**
* Init
*/
public function init()
{
if( $this->security() )
{
$this->authorize();
}
}
/**
* Security
*/
private function security()
{
if ( '127.0.0.1' == $_SERVER['REMOTE_ADDR']
&& file_exists( __DIR__ . '/.security' ) )
{
return true;
}
else
{
return false;
}
}
/**
* Authorize
*/
private function authorize()
{
if( isset( $_GET['unlock'] ) )
{
echo $this->run();
}
else
{
echo '<pre>Unauthorized.</pre>' . PHP_EOL;
}
}
/**
* Run
*
* Run, if authorized.
*
* @return string $html
*/
private function run()
{
if( isset( $_GET['run'] ) )
{
$file = [];
$file['text']['resp'] = '';
$file = $this->getDesc( $file );
$file = $this->getPaths( $file );
$file = $this->getFiles( $file );
$file = $this->getInfo( $file );
foreach( $file['files'] as $cnt => $name )
{
$item = [];
$item = $this->preProcess( $file, $item, $name );
if ( $this->opts['dev'] && $cnt >= $this->opts['max']['files'] )
{
break;
}
$item = $this->process( $file, $item );
$file = $this->postProcess( $file, $item );
}
$html = $this->getPageHTML( $file );
return $html;
}
else
{
echo '<pre>You wish to run the script?</pre>' . PHP_EOL;
}
}
/**
* Get the Description (Purpose) of This File
*
* @param array $file
*
* @return array
*/
private function getDesc( $file )
{
$file['text']['desc'] = '';
$file['text']['desc'] = '<div class="description">';
$file['text']['desc'] .= '<p>Converts valid CSS to a PHP data array and <br>';
$file['text']['desc'] .= ' saves it as a file.</p>';
$file['text']['desc'] .= '</div>' . PHP_EOL;
$file['text']['desc'] .= '<div class="clear"></div>' . PHP_EOL;
$file['text']['desc'] .= PHP_EOL;
return $file;
}
/**
* Get the Paths to the Files to Process.
*
* @param array $file
*
* @return array
*/
private function getPaths( $file )
{
if( is_array( $file ) )
{
$file['root'] = rtrim( $_SERVER['DOCUMENT_ROOT'], '/' );
$file['path']['input'] = $file['root'];
$file['path']['input'] .= $this->opts['dir']['input'];
$file['path']['output'] = $file['root'];
$file['path']['output'] .= $this->opts['dir']['output'];
}
return $file;
}
/**
* Get the Files.
*
* @param array $file
*
* @return array
*/
private function getFiles( $file )
{
$file['files'] = null;
if( isset( $file['path']['input'] ) )
{
$match = $file['path']['input'] . '/*.css';
// $file['files'][0], $file['files'][1], $file['files'][2], etc...
$file['files'] = glob( $match );
}
return $file;
}
/**
* Get Info
*
* @param array $file
*
* @return array
*/
private function getInfo( $file )
{
$file['text']['info'] = null;
$str = '';
if( is_array( $file ) )
{
// Input path
$str .= isset( $file['path']['input'] ) ?
sprintf( '<br>Input Path: %s<br>%s', $file['path']['input'], PHP_EOL ) : '';
// Count of the files.
$str .= isset( $file['cnt'] ) ?
sprintf( '<br>Files: %s<br>%s', $file['cnt'], PHP_EOL ) : '';
// Output path
$str .= isset( $file['path']['output'] ) ?
sprintf( '<br>Output Path: %s<br><br>%s', $file['path']['output'], PHP_EOL ) : '';
}
$file['text']['info'] = $str;
return $file;
}
/**
* Pre Process
*
* @param array $file
* @param array $item
* @param string $name Full path to file, including the name
*
* @return array
*/
private function preProcess( $file, $item, $name )
{
if( is_array( $item ) )
{
$item['error'] = '';
$item['file']['input'] = $name;
$item = $this->getFileInfo( $file, $item );
}
return $item;
}
/**
* Process
*
* @param array $file
* @param array $item
*
* @return array
*/
private function process( $file, $item )
{
if( is_array( $item ) )
{
$item['error'] = '';
$item['php'] = '';
$item = $this->getFile( $file, $item );
$item = $this->clnFile( $file, $item );
$item = $this->addQuoFile( $file, $item );
$item = $this->repBrkFile( $file, $item );
$item = $this->genFncName( $file, $item );
$item = $this->genFile( $file, $item );
}
return $item;
}
/**
* Post Process
*
* @param array $file
* @param array $item
*
* @return array
*/
private function postProcess( $file, $item )
{
if ( is_array( $item ) )
{
$item['file']['output'] = str_replace( '.css', '.php', $item['file']['output'] );
$file['text']['resp'] .= $this->printFile( $file, $item );
}
return $file;
}
/**
* Get File Info
*
* @param array $file
* @param array $item
*
* @return array
*/
private function getFileInfo( $file, $item )
{
$item['file']['name'] = null;
$item['file']['base'] = null;
if( isset( $item['file']['input'] ) )
{
// Start with the path.
$item['file']['output'] = $file['path']['output'];
// Get the file name using pathinfo().
$item['file']['output'] .= '/' . pathinfo( $item['file']['input'], PATHINFO_BASENAME );
// Convert .css to .php
$item['file']['output'] = str_replace( '.css', '.php', $item['file']['output'] );
// Get the file name from pathinfo()
$item['file']['name'] = pathinfo( $item['file']['input'], PATHINFO_BASENAME );
// Replace the .css with .php
$item['file']['name'] = str_replace( '.css', '.php', $item['file']['name'] );
// Get the base name (no extension), using pathinfo().
$item['file']['base'] = pathinfo( $item['file']['input'], PATHINFO_FILENAME );
}
return $item;
}
/**
* Get File
*
* Gets the file as an array
*
* @example file( 'style.css', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES );
*
* @param array $file
* @param array $item
*
* @return array
*/
private function getFile( $file, $item )
{
if( isset( $item['file']['input'] ) )
{
if( file_exists( $item['file']['input'] ) )
{
$item['text']['lines'] = file( $item['file']['input'], FILE_SKIP_EMPTY_LINES );
}
}
return $item;
}
/**
* Clean the File (Return as a String)
*
* Remove all comments and extra line breaks to leave clean,
* well formatted CSS. This can then be processed by replacing
* the { with => [, the } with ], and then... placing quotes
* around all selectors and attributes. This may require a third
* step once the cleaning is finished.
*
* @param array $file
* @param array $item
*
* @return $item Converted from lines to a single string.
*/
private function clnFile( $file, $item )
{
$text = '';
$max = 36;
$skip = 0;
if( isset( $item['text']['lines'] ) )
{
foreach( $item['text']['lines'] as $cnt => $line )
{
// Remove extra line returns.
$line = str_replace( "\n\n", '\n', $line );
if( $this->opts['dev'] && $cnt == $max )
{
break;
}
// Comment start.
if( $this->iss( $line, '/*' ) || $skip )
{
$skip = 1;
}
// Comment end.
if( $this->iss( $line, '*/' ) && ! $skip )
{
$skip = 0;
}
// Skip single line comment.
if( $this->iss( $line, '/*' ) && $this->iss( $line, '*/' ) )
{
continue;
}
// Process only lines containing valid CSS.
if( ! $this->isCSS( $line ) )
{
continue;
}
// Skip empty lines.
if( empty( $line ) )
{
continue;
}
$this->opts['dev'] ? printf( '<pre>' . $cnt . ': ' . $line . '<br>' ) : '';
$text .= $line;
} // Loop
$item['text']['input'] = $text;
} // if
if( $this->opts['dev0'] )
{
pre_dump( $item['text']['input'], 0 );
}
return $item;
}
/**
* Process the File
*
* Convert.
*
* @param array $file
* @param array $item
*
* @return array
*/
/*
$node[0] = null;
$pair[0] = null;
$node[1] = null;
$pair[1] = null;
$node[2] = null;
$pair[2] = null;
// first forward bracket bumps node from null to 0
@media all {
$node[0] = true;
$pair[0] = false;
// second forward bracket with no pair bumps node to 1
body {
$node[0] = true;
$pair[0] = false;
// first pairing bumps pair to true (same level as node).
font: 12pt/1.5 sans-serif;
$pair[0] = true;
background-color: hsl(0, 0%, 100%);
color: hsl(0, 0%, 12.5%);
min-width: 240px;
max-width: 1056px;
display: block;
margin: 0 auto;
padding: 16px;
// First closing bracket bumps node/pair to false.
}
$node[1] = false;
$pair[1] = false;
// Next forward bracket bumps node back up.
@media (min-width:800px) {
$node[1] = true;
$pair[1] = false;
// Next forward bracket bumps node up.
html {
$node[2] = true;
$pair[2] = false;
// First pairing bumps level pair up one.
width: 1056px;
$pair[2] = true;
}
$node[2] = false;
$pair[2] = false;
}
$node[1] = false;
$pair[1] = false;
}
$node[0] = false;
$pair[0] = false;
Should be no more than three (3) nodes deep.
*/
private function prcFile( $file, $item )
{
$item['php'] = null;
$skip = 0;
//
$node[0] = false;
$node[1] = false;
$node[2] = false;
$node[3] = false;
$left = '';
$right = '';
$level = null;
$max = 34;
//
if( ! isset( $item['text']['data'] ) )
{
return;
}
foreach( $item['text']['data'] as $cnt => $line )
{
// Reset $data on each loop.
$data = '';
// Remove the line returns (essential).
$line = str_replace( "\n", '', $line );
if( $this->opts['dev'] && $cnt == $max )
{
break;
}
// Comment start.
if( $this->iss( $line, '/*' ) || $skip )
{
$skip = 1;
}
// Comment end.
if( $this->iss( $line, '*/' ) && ! $skip )
{
$skip = 0;
}
// Skip single line comment.
if( $this->iss( $line, '/*' ) && $this->iss( $line, '*/' ) )
{
continue;
}
// Process only lines containing valid CSS.
if( ! $this->isCSS( $line ) )
{
continue;
}
// Skip empty lines.
if( empty( $line ) )
{
continue;
}
$this->opts['dev'] ? printf( '<pre>' . $cnt . ': ' . $line . '<br>' ) : '';
//============================== NODE 0 =================================
if( $this->iss( $line, '{' ) && ! $node[0] && ! $node[1] && ! $this->isMedia( $line ) )
{
$node[0] = true;
$level = ' '; // 0 (4)
$data .= $this->genNode( $line, $level );
$this->opts['dev2'] ? $data .= ' /* End Node 0 */' . PHP_EOL : '';
$node[0] = false;
}
//============================== NODE 1 =================================
if( $this->iss( $line, '{' ) && ! $node[1] && ! $node[2] && ! $node[3] && $this->isMedia( $line ) )
{
$node[1] = true;
$level = ' '; // 0 (4)
$this->opts['dev2'] ? $data = ' /* Begin Node 1 */' . PHP_EOL : '';
$data .= $this->genNode( $line, $level );
}
//============================== NODE 2 ===============================
elseif( $this->iss( $line, '{' ) && $node[1] && ! $node[2] && ! $node[3] )
{
$node[2] = true;
$level = ' '; // 1 (6)
$this->opts['dev2'] ? $data = ' /* Begin Node 2 */' . PHP_EOL : '';
$data .= $this->genNode( $line, $level );
}
//============================== NODE 3 =============================
elseif( $this->iss( $line, '{' ) && $node[1] && $node[2] && ! $node[3] )
{
$node[3] = true;
$level = ' '; // 2 (8)
$this->opts['dev2'] ? $data = ' /* Begin Node 3 */' . PHP_EOL : '';
$data .= $this->genNode( $line, $level );
}
elseif( $this->iss( $line, '{' ) && $this->iss( $line, '}' ) )
{
$data = $this->genNodeEmpty( $line, $level );
}
else
{
// Not captured
}
// ========================== SELECTOR ONLY =============================
if( $this->iss( $line, ':' ) && $this->iss( $line, ';' ) )
{
$level0 = ' ' . $level;
$data = $this->genPair( $line, $level0 );
}
//========================== CLOSE NODE 3 ===============================
if( $this->iss( $line, '}' ) && $node[1] && $node[2] && $node[3] )
{
$node[3] = false;
$data = ' ],' . PHP_EOL;
$this->opts['dev2'] ? $data .= ' /* Close Node 3 */' . PHP_EOL : '';
}
//=========================== CLOSE NODE 2 ==============================
if( $this->iss( $line, '}' ) && $node[1] && $node[2] && ! $node[3] )
{
$node[2] = false;
$data = ' ],' . PHP_EOL;
$this->opts['dev2'] ? $data .= ' /* Close Node 2 */' . PHP_EOL : '';
}
//=========================== CLOSE NODE 1 ==============================
// Node 1 is always a media query.
if( $this->iss( $line, '}' ) && $node[1] && ! $node[2] && ! $node[3] && $this->isMedia( $line ) )
{
$node[1] = false;
// Should be the end of the line, man.
$data = ' ],' . PHP_EOL;
$this->opts['dev2'] ? $data .= ' /* Close Node 1 */' . PHP_EOL : '';
}
//=========================== CLOSE NODE 0 ==============================
// Node 0 is always a non-Media query
if( $node[0] && ! $node[1] && ! $node[2] && ! $node[3] && ! $this->isMedia( $line ) )
{
$node[0] = false;
// Should be the end of the line, man.
$data = ' ],' . PHP_EOL;
$this->opts['dev2'] ? $data .= ' /* Close Node 0 */' . PHP_EOL : '';
}
//====================================================
$item['php'] .= $data;
} // Loop
// Array is closed in the function body function.
return $item;
}
/**
* Generate Node
*
* @param $line
*
* @return string;
*/
private function genNode( $line, $level )
{
$left = null;
$right = null;
$ex = explode( '{', $line );
if( ! empty( $ex[0] ) )
{
$left = sprintf( "'%s'", trim( $ex[0] ) );
}
if( isset( $ex[1] ) )
{
$ex[1] = str_replace( "\n", '', $ex[1] );
$ex[1] = trim( $ex[1] );
if( strlen( $ex[1] ) > 0 )
{
$right = sprintf( "'%s'", $ex[1] );
}
}
$data = sprintf( '%s%s => [ %s%s', $level, $left, $right, PHP_EOL );
$data .= $this->genPair( $line, $level );
$data .= $level . '],' . PHP_EOL;
return $data;
}
/**
* Generate Pairing
*
* @param $line
*/
private function genPair( $line, $level )
{
$left = null;
$right = null;
$line = rtrim( $line, ';' );
$ex = explode( ':', $line );
if( ! empty( $ex[0] ) )
{
$left = sprintf( "'%s'", trim( $ex[0] ) );
}
if( ! empty( $ex[1] ) )
{
$right = sprintf( "'%s'", trim( $ex[1] ) );
}
return sprintf( '%s%s => %s,%s', $level, $left, $right, PHP_EOL );
}
/**
* Generate Node
*
* @param $line
*
* @return string;
*/
private function genNodeEmpty( $line, $level )
{
$left = null;
$right = null;
$ex = explode( '{', $line );
if( ! empty( $ex[0] ) )
{
$left = sprintf( "'%s'", trim( $ex[0] ) );
}
$right = $level . '],' . PHP_EOL;
return sprintf( '%s%s => [ %s%s', $level, $left, $right, PHP_EOL );
}
/**
* Check Line
*
* @param string $line
*
* @return bool
*/
private function chkLine( $line )
{
// Skip empty lines.
if( ! empty( $line ) )
{
return true;
}
else
{
return false;
}
}
/**
* Check Data
*
* @param string $data
*
* @return bool
*/
private function chkData( $data )
{
// Not empty, good!!!
if( ! empty( $data ) && ! is_array( $data ) )
{
return true;
}
else
{
pre_dump( 'Problem with the data, Houston' );
return false;
}
}
/**
* Process Line
*
* Moved to Process File, but left here for comparison.
*
* @param array $item
* @param string $line
* @param int $cnt
*
* @return string|bool
*/
private function prcLine( $item, $line, $cnt )
{
// Skip empty lines.
if( ! empty( $line ) )
{
// Change colons to arrows on selectors only.
if( $this->isSelector( $line ) && ! $this->isMedia( $line ) && ! $this->isPseudo( $line ) )
{
$line = str_replace( ':', '=>', $line );
}
if( $this->iss( $line, '{' ) )
{
//$line = $line . $item['line']['sel'];
}
// Remove double line spacing for an array.
$line = str_replace( "\n\n", "\n", $line );
// Change the brackets., one of these is media close.
$line = str_replace( '{', '[', $line );
// Remove all semi-colons.
$line = str_replace( ';', '', $line );
// Replace the right bracket. Add a comma.
$line = str_replace( '}', '],', $line );
// Change '[' to '=> ['.
$line = str_replace( '[', '=> [', $line );
// Add quotes around all selectors and attributes.
$line = $this->addQuotes( $line );
return $line;
}
else
{
return false;
}
}
/**
* Is a Media Query
*
* @param string $line
*
* @return bool
*/
private function isMedia( $line )
{
if( $this->iss( $line, '@media' ) && $this->iss( $line, '{' ) )
{
return true;
}
else
{
return false;
}
}
/**
* Is a Comment
*
* @param string $line
*
* @return bool
*/
private function isComment( $line )
{
if( $this->iss( $line, '/*' )
|| $this->iss( $line, '*/' )
|| $this->iss( $line, '*' )
|| $this->iss( $line, ':' ) )
{
return true;
}
else
{
return false;
}
}
/**
* Is a Element.
*
* @param string $line
*
* @return bool
*/
private function isElement( $line )
{
if( $this->iss( $line, '{' ) && ! $this->isMedia( $line ) && ! $this->isPseudo( $line ) )
{
return true;
}
else
{
return false;
}
}
/**
* Is a Multi Line Selector
*
* @param string $line
*
* @return bool
*/
private function isMultiSel( $line )
{
if( // Comma, but no semi-colon.
( $this->iss( $line, ',' ) && ! $this->iss( $line, ';' ) )
// No colons.
&& ! $this->iss( $line, ':' )
// No semi colons on their own.
&& ! $this->iss( $line, ';' )
// Not a comment.
&& ! $this->isComment( $line ) )
{
return true;
}
else
{
return false;
}
}
/**
* Is a Pseudo Element.
*
* @param string $line
*
* @return bool
*/
private function isPseudo( $line )
{
if( $this->iss( $line, '{' ) && $this->iss( $line, ':' ) )
{
return true;
}
else
{
return false;
}
}
/**
* Is a Selector Attribute Pairing
*
* MUST be called before colons are removed.
*
* @param string $line
*
* @return bool
*/
private function isSelector( $line )
{
if( $this->iss( $line, ':' ) && $this->iss( $line, ';' ) )
{
return true;
}
else
{
return false;
}
}
/**
* Add Quotes to the File
*
* Add single quotes around all CSS selectors and attributes.
*
* The simplest way to do this appears to break the file string
* into a line by line array (i.e. take apart on line breaks).
* Then, for each line, take it apart either on the '{' or on
* the ':', then trim the remaining on the left and the right,
* then put back together.
*
* The disadvantage to this approach is that well formed CSS
* has multiple selectors on separate lines. These need to be
* placed all on a single line (programmatically or manually),
* so that they will be dealt with in their entirety, instead
* of being left out on that line.
*
* @link https://www.php.net/manual/en/function.preg-split.php
*
* @example $keys = preg_split("/[\s,]+/", "hypertext language, programming");
*
* @param array $file
* @param array $item
*
* @return array
*/
private function addQuoFile( $file, $item )
{
$text = '';
if( isset( $item['text']['input'] ) )
{
if( $this->opts['dev2'] )
{
pre_dump( $item['text']['input'], 1 );
}
$lines = preg_split("/[\n]/", $item['text']['input'] );
foreach( $lines as $line )
{
$left = '';
$right = '';
$spc[1] = ' '; // Four spaces (minimum).
$spc[2] = ' '; // Six spaces
if( $this->iss( $line, '{' ) && ! $this->iss( $line, '}' ) )
{
$parts = explode( '{', $line );
if( isset( $parts[0] ) )
{
$left = trim( $parts[0] );
$left = sprintf( "'%s'", $left );
}
if( isset( $parts[1] ) )
{
$right = trim( $parts[1] );
$right = sprintf( "'%s'", $right );
}
// Add indentation ($spc#).
$line = sprintf( '%s%s {%s', $spc[1], $left, PHP_EOL );
$text .= $line;
}
// empty brackets (must keep).
elseif( $this->iss( $line, '{' ) && $this->iss( $line, '}' ) )
{
$parts = explode( '{', $line );
if( isset( $parts[0] ) )
{
$left = trim( $parts[0] );
$left = sprintf( "'%s'", $left );
}
if( isset( $parts[1] ) )
{
// No quotes. Should be just a bracket.
$right = trim( $parts[1] );
}
// Add indentation ($spc#).
$line = sprintf( '%s%s {%s%s', $spc[1], $left, $right, PHP_EOL );
$text .= $line;
}
elseif( $this->iss( $line, ':' ) && $this->iss( $line, ';' ) )
{
$parts = explode( ':', $line );
if( isset( $parts[0] ) )
{
$left = trim( $parts[0] );
$left = sprintf( "'%s'", $left );
}
if( isset( $parts[1] ) )
{
$right = trim( $parts[1] );
$right = trim( $right, ';' );
$right = sprintf( "'%s'", $right );
}
// Add indentation ($spc).and =>
$line = sprintf( '%s%s => %s,%s', $spc[2], $left, $right, PHP_EOL );
$text .= $line;
}
else
{
$text .= $spc[1] . $line . PHP_EOL;
}
}
$item['text']['quot'] = $text;
}
if( $this->opts['dev2'] )
{
pre_dump( $item['text']['quot'], 0 );
}
return $item;
}
/**
* Replace the Brackets on the File.
*
* Replaces the { and } with => [ and ],
* Do not replace the : in pseudo elements.
*
* @param string $str
*
* @return string
*/
private function repBrkFile( $file, $item )
{
$text = '';
if( isset( $item['text']['quot'] ) )
{
// Initialize
$text = $item['text']['quot'];
$text = str_replace( '{', '=> [', $text );
$text = str_replace( '}', '],', $text );
$text = str_replace( ';', '', $text );
$item['text']['output'] = $text;
}
if( $this->opts['dev1'] )
{
pre_dump( $item['text']['output'], 1 );
}
return $item;
}
/**
* Replace the Colons in the File
*
* Replace the : with =>, but not pseudo selectors.
* Break apart by line, and put together again to do this.
*
* @param array $file
* @param array $item
*
* @return array
*/
private function repClnFile( $file, $item )
{
$text = '';
if( isset( $item['text']['quot'] ) )
{
// Initialize
$text = $item['text']['quot'];
$text = str_replace( '{', '=> [', $text );
$text = str_replace( '}', '],', $text );
$text = str_replace( ';', '', $text );
$item['text']['output'] = $text;
}
if( $this->opts['dev1'] )
{
pre_dump( $item['text']['output'], 1 );
}
return $item;
}
/**
* Add Quotes
*
* Adds single quotes around CSS selectors and attributes.
*
* @param string $str
*
* @return string
*/
private function addQuotes( $line )
{
if( $this->iss( $line, '=>' ) )
{
$ex = explode( '=>', $line );
// Left side
if( isset( $ex[0] ) )
{
$left = trim( $ex[0] );
if( $this->iss( $ex[0], '@media' ) )
{
$left = sprintf( " '%s'", $left );
}
elseif( $this->iss( $ex[1], '[' ) )
{
$left = sprintf( " '%s'", $left );
}
else
{
$left = sprintf( " '%s'", $left );
}
}
// Right side
if( isset( $ex[1] ) && ! empty( $ex[1] ) )
{
$right = trim( $ex[1] );
if( ! $this->iss( $ex[1], '[' ) )
{
$right = sprintf( "'%s',", $right );
}
}
}
// Concatenate
if( ! empty( $left ) || ! empty( $right ) )
{
$line = sprintf( '%s => %s', $left, $right );
}
return $line;
}
/**
* Get the Function Name
*
* @param array $file
* @param array $item
*
* @return array
*/
private function genFncName( $file, $item )
{
if( isset( $item['file']['base'] ) )
{
$item['function']['name'] = null;
$item['function']['title'] = null;
$item['function']['name'] = sprintf( 'get_%s_data', $item['file']['base'] );
$item['function']['name'] = str_replace( '-', '_', $item['function']['name'] );
$title = str_replace( '_', ' ', $item['function']['name'] );
$item['function']['title'] = ucwords( $title );
}
return $item;
}
/**
* Generates the Data (Assoc Array as a String)
*
* @param array $file
* @param array $item
*
* @return array
*/
private function genDat( $file, $item )
{
$str = '';
$str .= ' $items = [' . PHP_EOL;
// Generates a CSS string.
foreach( $entities as $cnt => $entity )
{
if( $entity['type'] == $type['name'] )
{
if( $entity['use'] )
{
$str .= sprintf( " '%s' => [%s", $entity['name'], PHP_EOL );
foreach( $attributes as $attribute )
{
if( $attribute['use'] )
{
$str .= sprintf( " '%s' => '%s',%s",
$attribute['name'], $attribute['default'], PHP_EOL );
}
}
if( $cnt < count( $entities ) )
{
$str .= ' ],';
}
}
}
} // Loop
$str .= ' ];' . PHP_EOL;
$str .= PHP_EOL;
$str .= ' return $items;' . PHP_EOL;
$item['php'] = $str;
return $item;
}
/**
* Generates the File
*
* @param array $file
* @param array $item
*
* @return array
*/
private function genFile( $file, $item )
{
if( is_array( $item ) )
{
$item = $this->getPageHeader( $file, $item );
$item = $this->getFunctionBody( $file, $item );
if( $this->opts['dev3'] )
{
pre_dump( $item['php'] );
}
$item = $this->getFileSize( $file, $item );
$item = $this->getFileFooter( $file, $item );
}
return $item;
}
/**
* Page Header
*
* @param array $file
* @param array $item
*
* @return array
*/
private function getPageHeader( $file, $item )
{
// Initialize
$item['text']['print'] = '';
$str = '';
if( isset( $item['file']['name'] ) )
{
$str .= '<?php' . PHP_EOL;
$str .= '/**' . PHP_EOL;
$str .= sprintf( ' * %s%s', $this->opts['page']['title'], PHP_EOL );
$str .= ' *' . PHP_EOL;
$str .= sprintf( ' * File: %s%s', $item['file']['name'], PHP_EOL );
$str .= $this->getTimeStamp();
$str .= $this->getIDStamp();
$str .= ' *' . PHP_EOL;
$str .= sprintf( ' * (By: %s)%s', $this->opts['this']['file'], PHP_EOL );
$str .= ' */' . PHP_EOL;
$str .= 'namespace Earth3300\EC01;' . PHP_EOL;
$str .= PHP_EOL;
$str .= "if( ! defined( 'NDA' ) )" . PHP_EOL;
$str .= '{' . PHP_EOL;
$str .= " define( 'NDA', true );" . PHP_EOL;
$str .= '}' . PHP_EOL;
$str .= PHP_EOL;
$item['text']['print'] .= $str;
}
return $item;
}
/**
* Get Function Body
*
* @param array $file
* @param array $item
*
* @return array
*/
private function getFunctionBody( $file, $item )
{
$str = '';
if( isset( $item['function']['name'] ) )
{
$str .= '/**' . PHP_EOL;
$str .= sprintf( ' * %s%s', $item['function']['title'], PHP_EOL );
$str .= ' *' . PHP_EOL;
$str .= ' * @return array' . PHP_EOL;
$str .= ' */' . PHP_EOL;
$str .= sprintf( 'function %s()%s', $item['function']['name'], PHP_EOL );
$str .= '{' . PHP_EOL;
$str .= ' $item = [' . PHP_EOL;
$str .= $item['text']['output'];
$str .= ' ];' . PHP_EOL;
$str .= PHP_EOL;
$str .= ' return $item;' . PHP_EOL;
$str .= '}' . PHP_EOL;
$str .= PHP_EOL;
$item['text']['print'] .= $str;
}
return $item;
}
/**
* Time Stamp (Including Created Date)
*
* @return string
*/
private function getTimeStamp()
{
$str = '';
$str .= sprintf( ' * Created: %s%s', $this->opts['this']['date']['created'], PHP_EOL );
$str .= sprintf( ' * Updated: %s%s', date( 'Y-m-d' ), PHP_EOL );
$str .= sprintf( ' * Time: %s%s', date( 'H:i:s T' ), PHP_EOL );
return $str;
}
/**
* ID Stamp
*
* @return string
*/
private function getIDStamp()
{
$str = '';
$str .= ' * ID: ENG-ON-001' . PHP_EOL;
return $str;
}
/**
* Is (In) String (Helper Function)
*
* @param string $a Haystack
* @param string $b Needle
*
* @return bool
*/
function iss( $a, $b )
{
if( is_string( $a ) && is_string( $b )
&& strpos( $a, $b ) !== false )
{
return true;
}
else
{
return false;
}
}
/**
* Is CSS (Helper Function)
*
* @param string $line
*
* @return bool
*/
function isCSS( $line )
{
// Opening or closing
if( $this->iss( $line, '{' ) || $this->iss( $line, '}' ) )
{
return true;
}
// Selector : Attribute
elseif( $this->iss( $line, ':' ) && $this->iss( $line, ';' ) )
{
return true;
}
elseif( $this->iss( $line, ',' ) && ! $this->isComment( $line ) )
{
return true;
}
else
{
return false;
}
}
/**
* Get File Size
*
* @param array $file
* @param array $item
*
* @return array
*/
private function getFileSize( $file, $item )
{
$item['size'] = null;
if( isset( $item['text']['output'] ) )
{
$item['size'] = strlen( $item['text']['output'] );
}
return $item;
}
/**
* File Footer
*
* @param array $file
* @param array $item
*
* For use at the end of the file as needed.
*/
private function getFileFooter( $file, $item )
{
// Initialize
$str = '';
$str .= '/*';
$str .= ' End of File (';
$str .= $item['size'] . ' B).';
$str .= ' */' . PHP_EOL;
$str .= PHP_EOL;
// Add this string to the end...
$item['text']['print'] .= $str;
return $item;
}
/**
* Print the File
*
* @param array $file
* @param array $item
*
* @return array
*/
private function printFile( $file, $item )
{
$str = '';
if ( isset( $_GET['print'] ) )
{
if ( isset( $_POST['safety'] ) )
{
$str = '';
if( isset( $item['file']['output'] ) && isset( $item['php'] ) )
{
if( ! file_exists( $item['file']['output'] )
|| $this->opts['file']['overwrite'] )
{
$resp = file_put_contents( $item['file']['output'], $item['text']['print'] );
$str = sprintf(
'File: %s (%s B)<br>%s', $item['file']['output'], $resp, PHP_EOL );
}
else
{
$str = sprintf(
'File: %s (exists)<br>%s', $item['file']['output'], PHP_EOL );
}
}
}
}
return $str;
}
/**
* Get Form
*
* @return string|bool
*/
private function getForm()
{
if( isset( $_GET['ctrls'] ) )
{
// Initialize
$str = '';
$str .= '<form action="" method="post">' . PHP_EOL;
$str .= '<div>' . PHP_EOL;
$str .= '<input type="checkbox" name="safety" id="safety" required> ' . PHP_EOL;
$str .= '<input type="submit" class="btn btn-primary" value="Run">' . PHP_EOL;
$str .= '</div>' . PHP_EOL;
$str .= '</form>' . PHP_EOL;
return $str;
}
else
{
return false;
}
}
/**
* Wrap the HTML in Page HTML `<!DOCTYPE html>`, etc.
*
* Use basic settings. Assume no SEO necessary. Bootstrap CSS only.
*
* @param array $file
*
* @return string
*/
private function getPageHTML( $file )
{
$str = 'N/A';
if( is_array( $file ) )
{
$str = '';
$str = '<!DOCTYPE html>' . PHP_EOL;
$str .= '<html lang="en-CA" class="theme-dark">' . PHP_EOL;
$str .= '<head>' . PHP_EOL;
$str .= '<meta charset="UTF-8">' . PHP_EOL;
$str .= '<meta name="viewport" content="width=device-width, initial-scale=1"/>' . PHP_EOL;
$str .= sprintf( '<title>%s</title>%s',
$this->opts['this']['title'], PHP_EOL );
$str .= '<meta name="robots" content="noindex,nofollow" />' . PHP_EOL;
$str .= '<link rel=stylesheet href="/style.min.css">' . PHP_EOL;
$str .= '</head>' . PHP_EOL;
$str .= '<body>' . PHP_EOL;
$str .= '<main>' . PHP_EOL;
$str .= sprintf( '<h1>%s</h1>%s', $this->opts['this']['title'], PHP_EOL );
$str .= isset( $file['text']['desc'] ) ? $file['text']['desc'] : '';
$str .= $this->getForm();
$str .= isset( $file['text']['info'] ) ? $file['text']['info'] : '';
$str .= isset( $file['text']['resp'] ) ? $file['text']['resp'] : '';
if( isset( $_GET['display'] ) )
{
if( isset( $file['php'] ) )
{
$str .= '<pre>' . PHP_EOL;
$str .= $file['php'];
$str .= '</pre>' . PHP_EOL;
}
}
$str .= '</main>' . PHP_EOL;
$str .= '</html>' . PHP_EOL;
}
return $str;
}
} // End Class
if ( ! function_exists( 'pre_dump' ) ) {
/** Dumps a formatted string or array. */
function pre_dump( $arr, $continue = 1 ) {
if ( isset( $_GET['debug'] ) ) {
if (is_string( $arr ) ) {
$arr = str_replace( ['<','>'], ['&lt','&gt'], $arr );
}
echo "<pre>" . PHP_EOL;
var_dump( $arr );
if ( isset( $_GET['exit'] ) || ! $continue ) {
exit( '<br/>' . 'Done.' );
}
echo "</pre>" . PHP_EOL;
}
}
}
/**
* Global initialization function
*/
function ec01_css_printer()
{
$printer = new CssPrinter();
return $printer->init();
}
ec01_css_printer();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment