Created
November 3, 2019 21:08
-
-
Save earth3300/5763a0157f145d3f8649160741d1da3a to your computer and use it in GitHub Desktop.
Creates a CSV file based on loaded images.
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
<?php | |
/** | |
* EC01 CSV Printer (Images) | |
* | |
* Creates a CSV file from images. This CSV file can be imported into a | |
* database such as that used by WooCommerce and used in an online shop. | |
* | |
* @package Earth3300\EC01 | |
* @since 1.0.1 | |
* @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://github.com/earth3300/ec01-csv-printer | |
* | |
* File: printer.csv.php | |
* Created: 2018------ | |
* Updated: 2019-11-03 | |
* Time: 10:49 EDT | |
*/ | |
namespace Earth3300\EC01; | |
/** | |
* Prints a CSV file. | |
*/ | |
class CsvPrinter | |
{ | |
/** @var array Default options. */ | |
protected $opts = [ | |
'page' => [ | |
'title' => 'CSV Printer', | |
], | |
'date' => [ | |
'created' => '2019-07-17' | |
], | |
'dir' => [ | |
'input' => '/0/m/shop/2019/09/src', | |
'output' => '/0/m/shop/2019/09/csv', | |
], | |
'file' => [ | |
'type' => '.{jpg,png}', | |
'output' => [ | |
'csv' => '/products.csv', | |
], | |
], | |
'max' => [ | |
'files' => 50, // When picking up... | |
'length' => 3000000, // No more than 3MB please... :} | |
'cnt' => 40, // When putting together... | |
], | |
'site' => [ | |
'url' => 'http://wp00p.earth3300.local', | |
], | |
'media' => [ | |
'dir' => '/0/m', | |
], | |
'shop' => [ | |
'dir' => '/shop' | |
], | |
'product' => [ | |
'dir' => '/product', | |
], | |
'category' => 'nature', | |
'message' => [ | |
'na' => 'Not available.', | |
'write' => [ | |
'denied' => 'Write permission denied.' , | |
'success' => 'Write operation succeeded.', | |
'failure' => 'Write operation failed.', | |
], | |
], | |
]; | |
/** | |
* Init | |
*/ | |
public function init() | |
{ | |
if( $this->security() ) | |
{ | |
if( $this->environment() ) | |
{ | |
if( $this->authorize() ) | |
{ | |
$this->run(); | |
} | |
} | |
} | |
} | |
/** | |
* Security | |
* | |
* @return bool | |
*/ | |
private function security() | |
{ | |
if ( file_exists( __DIR__ . '/.security' ) ) | |
{ | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
/** | |
* Environment | |
* | |
* @return bool | |
*/ | |
private function environment() | |
{ | |
if ( '127.0.0.1' == $_SERVER['REMOTE_ADDR'] ) | |
{ | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
/** | |
* Authorize | |
* | |
* @return bool | |
*/ | |
private function authorize() | |
{ | |
if( isset( $_GET['unlock'] ) ) | |
{ | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
/** | |
* Run | |
* | |
* @return string|mixed | |
*/ | |
private function run() | |
{ | |
// Initialize. | |
$files = []; | |
if( isset( $_POST['safety'] ) ) | |
{ | |
$files['path'] = $this->getPaths(); | |
$files['text'] = $this->getFileDesc(); | |
$files = $this->getFileNames( $files ); | |
$files = $this->getFilesData( $files ); | |
$files = $this->getCsvData( $files ); | |
$files['resp'] = $this->putContents( $files ); | |
$files['msg'] = $this->getMessage( $files ); | |
} | |
$html = $this->getPageHTML( $files ); | |
echo $html; | |
} | |
/** | |
* Get the Paths to the Files to Process. | |
* | |
* @return array | |
*/ | |
private function getPaths() | |
{ | |
$path = []; | |
$path['root'] = rtrim( $_SERVER['DOCUMENT_ROOT'], '/' ); | |
$path['input'] = $path['root']; | |
$path['input'] .= $this->opts['dir']['input']; | |
$path['output'] = $path['root']; | |
$path['output'] .= $this->opts['dir']['output']; | |
$path['file']['output'] = $path['output']; | |
$path['file']['output'] .= $this->opts['file']['output']['csv']; | |
return $path; | |
} | |
/** | |
* The Page HTML | |
*/ | |
private function thePageHtml( $html ) | |
{ | |
echo $html; | |
} | |
/** | |
* Get File Names | |
* | |
* Get file names via "glob" and exclusion or a preconstructed list. Includes | |
* a check to ensure no more than the maximum number of files are returned. | |
* | |
* @return array | |
*/ | |
private function getFileNames( $files ) | |
{ | |
// Initialize. | |
$files['data'] = null; | |
$match = $files['path']['input'] . '/*' . $this->opts['file']['type']; | |
$items = glob( $match, GLOB_BRACE ); | |
if( is_array( $items ) && count( $items ) < $this->opts['max']['files'] ) | |
{ | |
foreach( $items as $i => $item ) | |
{ | |
$files['data'][$i]['path'] = $item; | |
} | |
} | |
else | |
{ | |
$files['data'] = false; | |
} | |
return $files; | |
} | |
/** | |
* File Excludes | |
*/ | |
private function rmvFileExcludes( $files ) | |
{ | |
$exclude = $this->opts['file']['print']; | |
if( in_array( $files['names'], $exclude ) ) | |
{ | |
// Incomplete... | |
} | |
} | |
/** | |
* Extract Useable Data from the Files Submitted. | |
* | |
* Gets available data from the files. | |
* | |
* @param array $files | |
* | |
* @return array $files | |
*/ | |
private function getFilesData( $files ) | |
{ | |
// Initalize counter | |
$files['cnt'] = count( $files['data'] ); | |
// Put the files in a local array. | |
if( isset( $files['data'] ) && count( $files['data'] ) > 0 ) | |
{ | |
// Loop through the items. | |
foreach ( $files['data'] as $cnt => $item ) | |
{ | |
/** Check to see if the file exists... */ | |
if ( file_exists( $item['path'] ) ) | |
{ | |
/** Get relevant file data. */ | |
$item = $this->getFileData( $item ); | |
// Add it to the array. | |
$files['data'][$cnt] = $item; | |
} | |
} | |
} | |
return $files; | |
} | |
/** | |
* Get the file name | |
* | |
* @example: | |
* array(5) { | |
* [0]=> | |
* string(24) "alberta-2297204_1920.jpg" | |
* [1]=> | |
* string(7) "alberta" | |
* [2]=> | |
* string(7) "2297204" | |
* [3]=> | |
* string(4) "1920" | |
* [4]=> | |
* string(3) "jpg" | |
* } | |
* | |
* @param array $file | |
* | |
* @return bool|array | |
*/ | |
private function getFileData( $item ) | |
{ | |
// Initialize. | |
// The name as originally. | |
$item['name'] = null; | |
// The first part of the name. | |
$item['initials'] = null; | |
// Product. | |
$item['product'] = null; | |
// The UID (Universal ID) (from the image name). | |
$item['date'] = null; | |
// Count of item (within date). | |
$item['cnt'] = null; | |
// Resolution (DPI). | |
$item['dpi'] = null; | |
// The image width (from the image name). | |
$item['width'] = null; | |
// The image height (from the image name). | |
$item['height'] = null; | |
// The image extension (not filtered). | |
$item['ext'] = null; | |
if ( is_string( $item['path'] ) && strlen( $item['path'] ) > 0 ) | |
{ | |
$pattern = $this->getPattern( $item ); | |
$item = $this->getPathFileName( $item ); | |
preg_match( $pattern, $item['name'], $matches ); | |
if( is_array( $matches ) && count( $matches) > 0 ) | |
{ | |
$item['name'] = isset( $matches[0] ) ? $matches[0] : ''; | |
$item['initials'] = isset( $matches[1] ) ? $matches[1] : ''; | |
$item['product'] = isset( $matches[2] ) ? $matches[2] : ''; | |
$item['date'] = isset( $matches[3] ) ? $matches[3] : ''; | |
$item['cnt'] = isset( $matches[4] ) ? $matches[4] : ''; | |
$item['dpi'] = isset( $matches[5] ) ? $matches[5] : ''; | |
$item['width'] = isset( $matches[6] ) ? $matches[6] : ''; | |
$item['height'] = isset( $matches[7] ) ? $matches[7] : ''; | |
$item['ext'] = isset( $matches[8] ) ? $matches[8] : ''; | |
} | |
} | |
return $item; | |
} | |
/* | |
array(9) { | |
[0]=> | |
string(39) "brs-bowl-201909-005-180dpi-1115x612.jpg" | |
[1]=> | |
string(3) "brs" | |
[2]=> | |
string(4) "bowl" | |
[3]=> | |
string(6) "201909" | |
[4]=> | |
string(3) "005" | |
[5]=> | |
string(3) "180" | |
[6]=> | |
string(4) "1115" | |
[7]=> | |
string(3) "612" | |
[8]=> | |
string(3) "jpg" | |
} | |
*/ | |
/** | |
* Get Path and File Parts | |
* | |
* @param array $item | |
* | |
* @return bool|array | |
*/ | |
private function getPathFileName( $item ) | |
{ | |
// Initialize. | |
$item['name'] = null; | |
if( is_string( $item['path'] ) ) | |
{ | |
$arr = explode( '/', $item['path'] ); | |
if( is_array( $arr ) && count( $arr ) > 1 ) | |
{ | |
$name = $arr[ count( $arr ) - 1 ]; | |
if( strlen( $name ) > 0 ) | |
{ | |
$item['name'] = $name; | |
} | |
else | |
{ | |
$item['name'] = false; | |
} | |
} | |
} | |
return $item; | |
} | |
/** | |
* Get the Regex Pattern | |
* | |
* @example 'mno-product-201909-001-300dpi-1200x800.jpg' | |
* @example /^([a-z]{1,35})-([0-9]{1,9})_([0-9]{1,5})\.([a-z]{1,4})$/" | |
* | |
* @param string $item | |
* | |
* @return string | |
*/ | |
private function getPattern( $item ) | |
{ | |
$str = ''; | |
// Regex Open | |
$str .= '/'; | |
// Beginning Anchor | |
$str .= '^'; | |
// Initials i.e. 'mno'. | |
$str .= '([a-z]{1,3})'; | |
// Product name (3-24 characters) i.e. 'widget'. | |
$str .= '-([a-z]{3,24})'; | |
// Date YYYYMM (6 digits). | |
$str .= '-([0-9]{4,6})'; | |
// Count ### (3 digits). | |
$str .= '-([0-9]{3,5})'; | |
// DPI ### (3 to 4 digits), then dpi. | |
$str .= '-([0-9]{2,4})dpi'; | |
// Resolution ###x### (Optional?) | |
$str .= '-([0-9]{2,4})x([0-9]{2,4})'; | |
// Extension. | |
$str .= '\.([a-z]{3,4})'; | |
// End Anchor. | |
$str .= '$'; | |
// Regex Close. | |
$str .= '/'; | |
return $str; | |
} | |
/** | |
* Get the File Path and Name | |
* | |
* @param array $files | |
* | |
* @return bool|string | |
*/ | |
private function getPrintFileName( $files ) | |
{ | |
if ( is_array( $files ) && ! empty( $files['path'] ) ) | |
{ | |
$file['name'] = $files['path']['output']; | |
$file['name'] .= $this->opts['file']['output']['csv']; | |
return $file['name']; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
/** | |
* Get the CSV Header | |
* | |
* ID: Incremental, Integer, Primary Key | |
* Type: Simple (Assigned automatically, unless otherwise). | |
* SKU: Camera ID | |
* Name: File Name | |
* | |
* @param array $files | |
* | |
* @return array | |
*/ | |
private function getCsvHeader( $files ) | |
{ | |
// Initialize | |
$csv = []; | |
/* | |
// The complete file name. | |
$item['name'] = null; | |
// The first part of the name. | |
$item['initials'] = null; | |
// Product. | |
$item['product'] = null; | |
// The UID (Universal ID) (from the image name). | |
$item['date'] = null; | |
// Count of item (within date). | |
$item['cnt'] = null; | |
// Resolution (DPI). | |
$item['dpi'] = null; | |
// The image width (from the image name). | |
$item['width'] = null; | |
// The image height (from the image name). | |
$item['height'] = null; | |
// The image extension (not filtered). | |
$item['ext'] = null; | |
*/ | |
// First row equals column names (4 only initially). | |
$csv = [ | |
[ 'name' => 'id', 'title' => 'ID', 'use' => 1, ], | |
[ 'name' => 'type', 'title' => 'Type', 'use' => 1, ], | |
[ 'name' => 'sku', 'title' => 'SKU', 'use' => 1, ], | |
[ 'name' => 'name', 'title' => 'Name', 'use' => 1, ], | |
[ 'name' => 'published', 'title' => 'Published', 'use' => 1, ], | |
[ 'name' => 'featured', 'title' => '"Is featured?"', 'use' => 1, ], | |
[ 'name' => 'visible', 'title' => '"Visibility in catalog"', 'use' => 1, ], | |
[ 'name' => 'price', 'title' => '"Regular Price"', 'use' => 1, ], | |
[ 'name' => 'categories', 'title' => '"Categories"', 'use' => 1, ], | |
[ 'name' => 'images', 'title' => 'Images', 'use' => 1, ], | |
]; | |
$str = ''; | |
foreach ( $csv as $cnt => $item ) | |
{ | |
if( $item['use'] ) | |
{ | |
// Add the Title | |
$str .= $item['title']; | |
// Add the comma. | |
$str .= ','; | |
} | |
} | |
// Remove the last comma. | |
$str = rtrim( $str, ',' ); | |
// Add a line ending (required). | |
$str .= PHP_EOL; | |
return $str; | |
} | |
/** | |
* Generates a CSV from an array. | |
* | |
* ID: Incremental, Integer, Primary Key | |
* Type: Simple (Assigned automatically, unless otherwise). | |
* SKU: Camera ID | |
* Name: File Name | |
* | |
* @param array $files | |
* | |
* @return array | |
*/ | |
private function getCsvData( $files ) | |
{ | |
// Put the files in a local array. | |
if( isset( $files['data'] ) && count( $files['data'] ) > 0 ) | |
{ | |
// Loop through the items. | |
foreach ( $files['data'] as $cnt => $item ) | |
{ | |
if ( ! isset( $item['uid'] ) ) | |
{ | |
continue; | |
} | |
// This should be an incremental id, primary key. | |
// Increment only if at least one key available. | |
$str .= isset( $item['uid'] ) ? $cnt . ',' : ''; | |
// Simple Product. | |
$str .= isset( $item['uid'] ) ? 'simple' . ',' : ''; | |
// Slug in WooCommerce. | |
$str .= isset( $item['uid'] ) ? $item['uid'] . ',' : ''; | |
// Name in WooCommerce. Title in WordPress. | |
$str .= isset( $item['stub'] ) ? '"' . ucfirst( $item['stub'] ) . '",' : ''; | |
// Published. | |
$str .= isset( $item['uid'] ) ? '1' . ',' : ''; | |
// Is featured?. | |
$str .= isset( $item['uid'] ) ? '0' . ',' : ''; | |
// Visibility (Hidden initially). | |
$str .= isset( $item['uid'] ) ? 'visible' . ',' : ''; | |
// Regular Price. | |
$str .= isset( $item['uid'] ) ? '150.00' . ',' : ''; | |
$str .= isset( $item['uid'] ) ? $this->opts['category'] . ',' : ''; | |
$str .= isset( $item['all'] ) ? $this->getImageUrl( $item ) : ''; | |
// Remove the trailing comma. | |
$str = rtrim( $str, ',' ); | |
$str .= PHP_EOL; | |
} | |
} | |
return $str; | |
} | |
/** | |
* Get Image URL Base | |
* | |
* @return string|bool | |
*/ | |
private function getImageUrl( $item ) | |
{ | |
// Initialize. | |
$url = ''; | |
$url .= $this->opts['site']['url']; | |
$url .= $this->opts['media']['dir']; | |
$url .= $this->opts['shop']['dir']; | |
$url .= $this->opts['product']['dir']; | |
if( strlen( $url ) > 0 ) | |
{ | |
return sprintf('"%s/%s"', $url, $item['all'] ); | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
/** | |
* Write Files to the Storage Medium. | |
* | |
* @param string $str | |
* | |
* @return bool | |
*/ | |
private function putContents( $files ) | |
{ | |
if ( isset( $_GET['display'] ) ) | |
{ | |
pre_dump( $files['csv'] ); | |
} | |
if ( isset( $_GET['print'] ) | |
&& isset( $files['csv'] ) && strlen( $files['csv'] ) > 0 ) | |
{ | |
$resp = file_put_contents( $files['print'], $files['csv'] ); | |
return $resp; | |
} | |
} | |
/** | |
* Get Message | |
* | |
* @param array $files | |
* | |
* @return string | |
*/ | |
private function getMessage( $files ) | |
{ | |
//is_string( $str ) && strlen( $str ) > 0 && strlen( $str ) < 1000 ) | |
if( is_array( $files ) && count( $files ) > 0 ) | |
{ | |
// Initialize. | |
$str = ''; | |
// Count of the files. | |
$str .= isset( $files['cnt'] ) ? | |
sprintf( '<p>Files: %s</p>%s', $files['cnt'], PHP_EOL ) : ''; | |
// Length of the files. | |
$str .= isset( $files['str'] ) ? | |
sprintf( '<p>Bytes: %s</p>%s', strlen ( $files['str'] ), PHP_EOL ) : ''; | |
// Length of the files. | |
$str .= isset( $files['resp'] ) ? | |
sprintf( '<p>Resp: %s</p>%s', $files['resp'], PHP_EOL ) : ''; | |
// Length of the files. | |
$str .= isset( $files['print'] ) ? | |
sprintf( '<p>File: %s</p>%s', $files['print'], PHP_EOL ) : ''; | |
return $str; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
/** | |
* File Description | |
* | |
* For use at the top of the file as needed. | |
*/ | |
private function getFileDesc() | |
{ | |
$str = ''; | |
$str .= '# ' . PHP_EOL; | |
$str .= '# Generated by: printer.csv.php' . PHP_EOL; | |
$str .= '# ' . PHP_EOL; | |
$str .= $this->getTimeStamp(); | |
$str .= '#' . PHP_EOL; | |
return $str; | |
} | |
/** | |
* Time Stamp (Including Created Date) | |
* | |
* @return string | |
*/ | |
private function getTimeStamp() | |
{ | |
$str = ''; | |
$str .= sprintf( '# Created: %s%s', | |
$this->opts['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; | |
} | |
/** | |
* File End | |
*/ | |
private function getFileEnd( $files ) | |
{ | |
// Initialize | |
$str = PHP_EOL; | |
$str .= '/*'; | |
$str .= ' End of File: printer.csv.php. '; | |
$str .= $files['size'] . ' B. '; | |
$str .= '*/' . PHP_EOL; | |
$str .= PHP_EOL; | |
// Add this string to the end... | |
$files['str'] .= $str; | |
return $files; | |
} | |
/** | |
* Get Form | |
* | |
* @return string | |
*/ | |
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" value="Run">' . PHP_EOL; | |
$str .= '</div>' . PHP_EOL; | |
$str .= '</form>' . PHP_EOL; | |
return $str; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
/** | |
* Get the Page HTML. | |
* | |
* @param array $files | |
* | |
* @return string | |
*/ | |
private function getPageHTML( $files ) | |
{ | |
$str = '<!DOCTYPE html>' . PHP_EOL; | |
$str .= '<html lang="en-CA" class="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['page']['title'], PHP_EOL ); | |
$str .= '<meta name="robots" content="noindex,nofollow" />' . PHP_EOL; | |
$str .= '<link rel=stylesheet href="/style.min.css">' . PHP_EOL; | |
$str .= '<style> main { min-height: 500px; overflow: hidden; }'; | |
$str .= ' input { display: inline; } </style>' . PHP_EOL; | |
$str .= '</head>' . PHP_EOL; | |
$str .= '<body>' . PHP_EOL; | |
$str .= '<main>' . PHP_EOL; | |
$str .= sprintf( '<h1 style="display:block;">%s</h1>%s', $this->opts['page']['title'], PHP_EOL ); | |
$str .= $this->getForm(); | |
$str .= isset( $files['msg'] ) ? $files['msg'] : ''; | |
$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( ['<','>'], ['<','>'], $arr ); | |
} | |
echo "<pre>" . PHP_EOL; | |
var_dump( $arr ); | |
if ( isset( $_GET['exit'] ) || ! $continue ) { | |
exit( '<br/>' . 'Done.' ); | |
} | |
echo "</pre>" . PHP_EOL; | |
} | |
} | |
} | |
/** | |
* CSV Printer | |
*/ | |
function ec01_csv_printer() | |
{ | |
$printer = new CsvPrinter(); | |
$printer->init(); | |
} | |
ec01_csv_printer(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment