mirror of
https://github.com/ToxicCrack/PrintABrick.git
synced 2025-05-18 13:10:08 -07:00
Refactor Utils
This commit is contained in:
parent
efde576d1c
commit
2a02cd19ef
@ -17,7 +17,7 @@
|
|||||||
{% for instruction in instructions %}
|
{% for instruction in instructions %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ instruction.description }}</td>
|
<td>{{ instruction.description }}</td>
|
||||||
<td>{{ utils.bytesToSize( remoteSize(instruction.uRL)) }}</td>
|
<td>{{ remoteSize(instruction.uRL) | bytesToSize }}</td>
|
||||||
<td><a href="{{ instruction.uRL }}">{{ remoteFilename(instruction.uRL) }}</a></td>
|
<td><a href="{{ instruction.uRL }}">{{ remoteFilename(instruction.uRL) }}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
{#http://stackoverflow.com/a/15303004#}
|
|
||||||
{% macro bytesToSize(bytes) %}
|
|
||||||
{% spaceless %}
|
|
||||||
{% set kilobyte = 1024 %}
|
|
||||||
{% set megabyte = kilobyte * 1024 %}
|
|
||||||
{% set gigabyte = megabyte * 1024 %}
|
|
||||||
{% set terabyte = gigabyte * 1024 %}
|
|
||||||
|
|
||||||
{% if bytes < kilobyte %}
|
|
||||||
{{ bytes ~ ' B' }}
|
|
||||||
{% elseif bytes < megabyte %}
|
|
||||||
{{ (bytes / kilobyte)|number_format(2, '.') ~ ' KB' }}
|
|
||||||
{% elseif bytes < gigabyte %}
|
|
||||||
{{ (bytes / megabyte)|number_format(2, '.') ~ ' MB' }}
|
|
||||||
{% elseif bytes < terabyte %}
|
|
||||||
{{ (bytes / gigabyte)|number_format(2, '.') ~ ' GB' }}
|
|
||||||
{% else %}
|
|
||||||
{{ (bytes / terabyte)|number_format(2, '.') ~ ' TB' }}
|
|
||||||
{% endif %}
|
|
||||||
{% endspaceless %}
|
|
||||||
{% endmacro %}
|
|
@ -8,7 +8,7 @@ imports:
|
|||||||
parameters:
|
parameters:
|
||||||
locale: en
|
locale: en
|
||||||
# rebrickable csv files root URL (http://rebrickable.com/media/downloads/ or local dir containing csv files)
|
# rebrickable csv files root URL (http://rebrickable.com/media/downloads/ or local dir containing csv files)
|
||||||
rebrickable_csv_url: 'http://rebrickable.com/media/downloads/'
|
rebrickable_downloads_url: 'http://rebrickable.com/media/downloads/'
|
||||||
|
|
||||||
framework:
|
framework:
|
||||||
#esi: ~
|
#esi: ~
|
||||||
@ -65,13 +65,13 @@ doctrine:
|
|||||||
naming_strategy: doctrine.orm.naming_strategy.underscore
|
naming_strategy: doctrine.orm.naming_strategy.underscore
|
||||||
auto_mapping: true
|
auto_mapping: true
|
||||||
|
|
||||||
# Swiftmailer Configuration
|
## Swiftmailer Configuration
|
||||||
swiftmailer:
|
#swiftmailer:
|
||||||
transport: "%mailer_transport%"
|
# transport: "%mailer_transport%"
|
||||||
host: "%mailer_host%"
|
# host: "%mailer_host%"
|
||||||
username: "%mailer_user%"
|
# username: "%mailer_user%"
|
||||||
password: "%mailer_password%"
|
# password: "%mailer_password%"
|
||||||
spool: { type: memory }
|
# spool: { type: memory }
|
||||||
|
|
||||||
knp_menu:
|
knp_menu:
|
||||||
twig:
|
twig:
|
||||||
@ -97,7 +97,7 @@ liip_imagine:
|
|||||||
filesystem_service: oneup_flysystem.media_filesystem
|
filesystem_service: oneup_flysystem.media_filesystem
|
||||||
rebrickable:
|
rebrickable:
|
||||||
stream:
|
stream:
|
||||||
wrapper: 'http://m.rebrickable.com/media/'
|
wrapper: 'http://rebrickable.com/media/'
|
||||||
|
|
||||||
resolvers:
|
resolvers:
|
||||||
default:
|
default:
|
||||||
|
@ -1 +0,0 @@
|
|||||||
services:
|
|
@ -2,15 +2,10 @@ services:
|
|||||||
app.twig_extension:
|
app.twig_extension:
|
||||||
class: AppBundle\Twig\AppExtension
|
class: AppBundle\Twig\AppExtension
|
||||||
public: false
|
public: false
|
||||||
arguments: ['@api.manager.rebrickable']
|
arguments: ['@api.manager.rebrickable', '@app.transformer.format']
|
||||||
tags:
|
tags:
|
||||||
- { name: twig.extension }
|
- { name: twig.extension }
|
||||||
|
|
||||||
app.relation.mapper:
|
|
||||||
class: AppBundle\Utils\RelationMapper
|
|
||||||
arguments:
|
|
||||||
- ['%kernel.root_dir%/Resources/relations']
|
|
||||||
|
|
||||||
service.renderer.stl:
|
service.renderer.stl:
|
||||||
class: AppBundle\Service\StlRendererService
|
class: AppBundle\Service\StlRendererService
|
||||||
arguments: ['%kernel.root_dir%/Resources/povray_layout/layout.tmpl', '%povray_bin%','%stl2pov_bin%']
|
arguments: ['%kernel.root_dir%/Resources/povray_layout/layout.tmpl', '%povray_bin%','%stl2pov_bin%']
|
||||||
|
8
app/config/service/util.yml
Normal file
8
app/config/service/util.yml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
services:
|
||||||
|
app.transformer.format:
|
||||||
|
class: AppBundle\Transformer\FormatTransformer
|
||||||
|
|
||||||
|
app.relation.mapper:
|
||||||
|
class: AppBundle\Util\RelationMapper
|
||||||
|
arguments:
|
||||||
|
- ['%kernel.root_dir%/Resources/relations']
|
@ -2,7 +2,7 @@ imports:
|
|||||||
- { resource: service/repository.yml }
|
- { resource: service/repository.yml }
|
||||||
- { resource: service/api.yml }
|
- { resource: service/api.yml }
|
||||||
- { resource: service/loader.yml }
|
- { resource: service/loader.yml }
|
||||||
- { resource: service/manager.yml }
|
- { resource: service/util.yml }
|
||||||
- { resource: service/service.yml }
|
- { resource: service/service.yml }
|
||||||
- { resource: service/form.yml }
|
- { resource: service/form.yml }
|
||||||
- { resource: service/menu.yml }
|
- { resource: service/menu.yml }
|
18
src/AppBundle/Transformer/FormatTransformer.php
Normal file
18
src/AppBundle/Transformer/FormatTransformer.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Transformer;
|
||||||
|
|
||||||
|
|
||||||
|
class FormatTransformer
|
||||||
|
{
|
||||||
|
function bytesToSize($bytes, $precision = 2)
|
||||||
|
{
|
||||||
|
if ($bytes == 0)
|
||||||
|
return "0.00 B";
|
||||||
|
|
||||||
|
$suffix = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
|
||||||
|
$exponent = floor(log($bytes, 1024));
|
||||||
|
|
||||||
|
return round($bytes/pow(1024, $exponent), $precision).' '.$suffix[(int)$exponent];
|
||||||
|
}
|
||||||
|
}
|
@ -3,20 +3,25 @@
|
|||||||
namespace AppBundle\Twig;
|
namespace AppBundle\Twig;
|
||||||
|
|
||||||
use AppBundle\Api\Manager\RebrickableManager;
|
use AppBundle\Api\Manager\RebrickableManager;
|
||||||
|
use AppBundle\Transformer\FormatTransformer;
|
||||||
|
|
||||||
class AppExtension extends \Twig_Extension
|
class AppExtension extends \Twig_Extension
|
||||||
{
|
{
|
||||||
/** @var RebrickableManager */
|
/** @var RebrickableManager */
|
||||||
private $rebrickableAPIManager;
|
private $rebrickableAPIManager;
|
||||||
|
|
||||||
|
/** @var FormatTransformer */
|
||||||
|
private $formatTransformer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AppExtension constructor.
|
* AppExtension constructor.
|
||||||
*
|
*
|
||||||
* @param RebrickableManager $rebrickableAPIManager
|
* @param RebrickableManager $rebrickableAPIManager
|
||||||
*/
|
*/
|
||||||
public function __construct($rebrickableAPIManager)
|
public function __construct($rebrickableAPIManager, $formatTransformer)
|
||||||
{
|
{
|
||||||
$this->rebrickableAPIManager = $rebrickableAPIManager;
|
$this->rebrickableAPIManager = $rebrickableAPIManager;
|
||||||
|
$this->formatTransformer = $formatTransformer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFilters()
|
public function getFilters()
|
||||||
@ -24,6 +29,7 @@ class AppExtension extends \Twig_Extension
|
|||||||
return [
|
return [
|
||||||
new \Twig_SimpleFilter('partImage', [$this, 'partImage']),
|
new \Twig_SimpleFilter('partImage', [$this, 'partImage']),
|
||||||
new \Twig_SimpleFilter('setImage', [$this, 'setImage']),
|
new \Twig_SimpleFilter('setImage', [$this, 'setImage']),
|
||||||
|
new \Twig_SimpleFilter('bytesToSize', [$this, 'bytesToSize']),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +43,7 @@ class AppExtension extends \Twig_Extension
|
|||||||
|
|
||||||
public function partImage($number, $color = null)
|
public function partImage($number, $color = null)
|
||||||
{
|
{
|
||||||
return '/parts/ldraw/'.($color ? $color : '-1').'/'.$number.'.png';
|
return '/parts/ldraw/'.($color !== null ? $color : '-1').'/'.$number.'.png';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setImage($number)
|
public function setImage($number)
|
||||||
@ -45,6 +51,10 @@ class AppExtension extends \Twig_Extension
|
|||||||
return '/sets/'.strtolower($number).'.jpg';
|
return '/sets/'.strtolower($number).'.jpg';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function bytesToSize($bytes, $precision = 2) {
|
||||||
|
return $this->formatTransformer->bytesToSize($bytes, $precision);
|
||||||
|
}
|
||||||
|
|
||||||
public function remoteSize($url)
|
public function remoteSize($url)
|
||||||
{
|
{
|
||||||
$ch = curl_init($url);
|
$ch = curl_init($url);
|
||||||
|
206
src/AppBundle/Util/LDModelParser.php
Normal file
206
src/AppBundle/Util/LDModelParser.php
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Util;
|
||||||
|
|
||||||
|
use AppBundle\Exception\ErrorParsingLineException;
|
||||||
|
|
||||||
|
class LDModelParser
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Parse LDraw model .dat file content and return associative array in format:
|
||||||
|
* [
|
||||||
|
* 'id' => string
|
||||||
|
* 'name' => string
|
||||||
|
* 'category' => string
|
||||||
|
* 'keywords' => []
|
||||||
|
* 'author' => string
|
||||||
|
* 'modified' => DateTime
|
||||||
|
* 'type' => string
|
||||||
|
* 'subparts' => [],
|
||||||
|
* 'licence' => string
|
||||||
|
* ].
|
||||||
|
*
|
||||||
|
* LDraw.org Standards: Official Library Header Specification (http://www.ldraw.org/article/398.html)
|
||||||
|
*
|
||||||
|
* @throws ErrorParsingLineException
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function parse($string)
|
||||||
|
{
|
||||||
|
$model = [
|
||||||
|
'id' => null,
|
||||||
|
'name' => null,
|
||||||
|
'category' => null,
|
||||||
|
'keywords' => [],
|
||||||
|
'author' => null,
|
||||||
|
'modified' => null,
|
||||||
|
'type' => null,
|
||||||
|
'subparts' => [],
|
||||||
|
'parent' => null,
|
||||||
|
'license' => null,
|
||||||
|
];
|
||||||
|
|
||||||
|
$firstLine = false;
|
||||||
|
foreach(explode("\n", $string) as $line) {
|
||||||
|
$line = trim($line);
|
||||||
|
|
||||||
|
// Comments or META Commands
|
||||||
|
if (strpos($line, '0 ') === 0) {
|
||||||
|
$line = preg_replace('/^0 /', '', $line);
|
||||||
|
|
||||||
|
// 0 <CategoryName> <PartDescription>
|
||||||
|
if (!$firstLine) {
|
||||||
|
$array = explode(' ', ltrim(trim($line, 2), '=_~'));
|
||||||
|
$model['category'] = isset($array[0]) ? $array[0] : '';
|
||||||
|
$model['name'] = preg_replace('/ {2,}/', ' ', ltrim($line, '=_'));
|
||||||
|
|
||||||
|
$firstLine = true;
|
||||||
|
}
|
||||||
|
// 0 !CATEGORY <CategoryName>
|
||||||
|
elseif (strpos($line, '!CATEGORY ') === 0) {
|
||||||
|
$model['category'] = trim(preg_replace('/^!CATEGORY /', '', $line));
|
||||||
|
}
|
||||||
|
// 0 !KEYWORDS <first keyword>, <second keyword>, ..., <last keyword>
|
||||||
|
elseif (strpos($line, '!KEYWORDS ') === 0) {
|
||||||
|
$model['keywords'] = explode(', ', preg_replace('/^!KEYWORDS /', '', $line));
|
||||||
|
}
|
||||||
|
// 0 Name: <Filename>.dat
|
||||||
|
elseif (strpos($line, 'Name: ') === 0 && !isset($header['id'])) {
|
||||||
|
$model['id'] = preg_replace('/(^Name: )(.*)(.dat)/', '$2', $line);
|
||||||
|
}
|
||||||
|
// 0 Author: <Realname> [<Username>]
|
||||||
|
elseif (strpos($line, 'Author: ') === 0) {
|
||||||
|
$model['author'] = preg_replace('/^Author: /', '', $line);
|
||||||
|
}
|
||||||
|
// 0 !LDRAW_ORG Part|Subpart|Primitive|48_Primitive|Shortcut (optional qualifier(s)) ORIGINAL|UPDATE YYYY-RR
|
||||||
|
elseif (strpos($line, '!LDRAW_ORG ') === 0) {
|
||||||
|
$type = preg_replace('/(^!LDRAW_ORG )(.*)( UPDATE| ORIGINAL)(.*)/', '$2', $line);
|
||||||
|
|
||||||
|
$model['type'] = $type;
|
||||||
|
|
||||||
|
// Last modification date in format YYYY-RR
|
||||||
|
$date = preg_replace('/(^!LDRAW_ORG )(.*)( UPDATE | ORIGINAL )(.*)/', '$4', $line);
|
||||||
|
if (preg_match('/^[1-2][0-9]{3}-[0-9]{2}$/', $date)) {
|
||||||
|
$model['modified'] = \DateTime::createFromFormat('Y-m-d H:i:s', $date.'-01 00:00:00');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt | 0 !LICENSE Not redistributable : see NonCAreadme.txt
|
||||||
|
elseif (strpos($line, '!LICENSE ') === 0) {
|
||||||
|
$model['license'] = preg_replace('/(^!LICENSE )(.*) : (.*)$/', '$2', $line);
|
||||||
|
}
|
||||||
|
} elseif (strpos($line, '1 ') === 0) {
|
||||||
|
$id = strtolower($this->getReferencedModelNumber($line));
|
||||||
|
|
||||||
|
if (isset($model['subparts'][$id])) {
|
||||||
|
$model['subparts'][$id] = $model['subparts'][$id] + 1;
|
||||||
|
} else {
|
||||||
|
$model['subparts'][$id] = 1;
|
||||||
|
}
|
||||||
|
} elseif (!empty($line) && !in_array($line[0], ['2', '3', '4', '5'])) {
|
||||||
|
throw new ErrorParsingLineException($model['id'],$line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->isSticker($model['name'], $model['id'])) {
|
||||||
|
$model['type'] = 'Sticker';
|
||||||
|
} elseif (count($model['subparts']) == 1 && in_array($model['type'], ['Part Alias', 'Shortcut Physical_Colour', 'Shortcut Alias', 'Part Physical_Colour'])) {
|
||||||
|
$model['parent'] = array_keys($model['subparts'])[0];
|
||||||
|
} elseif (($parent = $this->getPrintedModelParentNumber($model['id'])) && !in_array($model['type'], ['48_Primitive', '8_Primitive', 'Primitive', 'Subpart'])) {
|
||||||
|
$model['type'] = 'Printed';
|
||||||
|
$model['parent'] = $parent;
|
||||||
|
} elseif ($parent = $this->getObsoleteModelParentNumber($model['name'])) {
|
||||||
|
$model['parent'] = $parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $model;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get file reference from part line.
|
||||||
|
*
|
||||||
|
* Line type 1 is a sub-file reference. The generic format is:
|
||||||
|
* 1 <colour> x y z a b c d e f g h i <file>
|
||||||
|
*
|
||||||
|
* LDraw.org Standards: File Format 1.0.2 (http://www.ldraw.org/article/218.html)
|
||||||
|
*
|
||||||
|
* @param $line
|
||||||
|
*
|
||||||
|
* @return string|null Filename of referenced part
|
||||||
|
*/
|
||||||
|
public function getReferencedModelNumber($line)
|
||||||
|
{
|
||||||
|
$line = ($line);
|
||||||
|
|
||||||
|
if (preg_match('/^1(.*) (.*)\.dat$/', strtolower($line), $matches)) {
|
||||||
|
return str_replace('\\', DIRECTORY_SEPARATOR, $matches[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get printed part parent id.
|
||||||
|
*
|
||||||
|
* part name in format:
|
||||||
|
* nnnPxx, nnnnPxx, nnnnnPxx, nnnaPxx, nnnnaPxx (a = alpha, n= numeric, x = alphanumeric)
|
||||||
|
*
|
||||||
|
* http://www.ldraw.org/library/tracker/ref/numberfaq/
|
||||||
|
*
|
||||||
|
* @param $id
|
||||||
|
*
|
||||||
|
* @return string|null LDraw number of printed part parent
|
||||||
|
*/
|
||||||
|
public function getPrintedModelParentNumber($id)
|
||||||
|
{
|
||||||
|
if (preg_match('/(^.*)(p[0-9a-z]{2,3})$/', $id, $matches)) {
|
||||||
|
return $matches[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if part is shortcut part of stricker and part.
|
||||||
|
*
|
||||||
|
* part name in format:
|
||||||
|
* nnnDnn, nnnnDnn, nnnnnDnn (a = alpha, n= numeric, x = alphanumeric)
|
||||||
|
*
|
||||||
|
* http://www.ldraw.org/library/tracker/ref/numberfaq/
|
||||||
|
*
|
||||||
|
* @param $name
|
||||||
|
* @param $number
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isSticker($name, $number)
|
||||||
|
{
|
||||||
|
if (strpos($name, 'Sticker') === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if in format n*Daa == sticker
|
||||||
|
return preg_match('/(^.*)(d[0-9]{2})$/', $number);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get parent of obsolete part kept for reference.
|
||||||
|
*
|
||||||
|
* part description in format:
|
||||||
|
* ~Moved to {new_number}
|
||||||
|
*
|
||||||
|
* http://www.ldraw.org/article/398.html (Appendix II (02-Oct-06))
|
||||||
|
*
|
||||||
|
* @param $name
|
||||||
|
*
|
||||||
|
* @return string|null Filename of referenced part
|
||||||
|
*/
|
||||||
|
public function getObsoleteModelParentNumber($name)
|
||||||
|
{
|
||||||
|
if (preg_match('/^(~Moved to )(.*)$/', $name, $matches)) {
|
||||||
|
return str_replace('\\', DIRECTORY_SEPARATOR, $matches[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace AppBundle\Utils;
|
namespace AppBundle\Util;
|
||||||
|
|
||||||
use Symfony\Component\Finder\Finder;
|
use Symfony\Component\Finder\Finder;
|
||||||
use Symfony\Component\OptionsResolver\Exception\InvalidArgumentException;
|
use Symfony\Component\OptionsResolver\Exception\InvalidArgumentException;
|
@ -1,223 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace AppBundle\Utils;
|
|
||||||
|
|
||||||
use AppBundle\Exception\FileNotFoundException;
|
|
||||||
use AppBundle\Exception\ParseErrorException;
|
|
||||||
use League\Flysystem\File;
|
|
||||||
|
|
||||||
class LDModelParser
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Parse LDraw model .dat file and return associative array in format:
|
|
||||||
* [
|
|
||||||
* 'id' => string
|
|
||||||
* 'name' => string
|
|
||||||
* 'category' => string
|
|
||||||
* 'keywords' => []
|
|
||||||
* 'author' => string
|
|
||||||
* 'modified' => DateTime
|
|
||||||
* 'type' => string
|
|
||||||
* 'subparts' => [],
|
|
||||||
* 'licence' => string
|
|
||||||
* ].
|
|
||||||
*
|
|
||||||
* LDraw.org Standards: Official Library Header Specification (http://www.ldraw.org/article/398.html)
|
|
||||||
*
|
|
||||||
* @throws FileNotFoundException|ParseErrorException
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function parse($file)
|
|
||||||
{
|
|
||||||
if (file_exists($file)) {
|
|
||||||
$model = [
|
|
||||||
'id' => null,
|
|
||||||
'name' => null,
|
|
||||||
'category' => null,
|
|
||||||
'keywords' => [],
|
|
||||||
'author' => null,
|
|
||||||
'modified' => null,
|
|
||||||
'type' => null,
|
|
||||||
'subparts' => [],
|
|
||||||
'parent' => null,
|
|
||||||
'license' => null,
|
|
||||||
];
|
|
||||||
|
|
||||||
try {
|
|
||||||
$handle = fopen($file, 'r');
|
|
||||||
|
|
||||||
if ($handle) {
|
|
||||||
$firstLine = false;
|
|
||||||
|
|
||||||
while (($line = fgets($handle)) !== false) {
|
|
||||||
$line = trim($line);
|
|
||||||
|
|
||||||
// Comments or META Commands
|
|
||||||
if (strpos($line, '0 ') === 0) {
|
|
||||||
$line = preg_replace('/^0 /', '', $line);
|
|
||||||
|
|
||||||
// 0 <CategoryName> <PartDescription>
|
|
||||||
if (!$firstLine) {
|
|
||||||
$array = explode(' ', ltrim(trim($line, 2), '=_~'));
|
|
||||||
$model['category'] = isset($array[0]) ? $array[0] : '';
|
|
||||||
$model['name'] = preg_replace('/ {2,}/', ' ', ltrim($line, '=_'));
|
|
||||||
|
|
||||||
$firstLine = true;
|
|
||||||
}
|
|
||||||
// 0 !CATEGORY <CategoryName>
|
|
||||||
elseif (strpos($line, '!CATEGORY ') === 0) {
|
|
||||||
$model['category'] = trim(preg_replace('/^!CATEGORY /', '', $line));
|
|
||||||
}
|
|
||||||
// 0 !KEYWORDS <first keyword>, <second keyword>, ..., <last keyword>
|
|
||||||
elseif (strpos($line, '!KEYWORDS ') === 0) {
|
|
||||||
$model['keywords'] = explode(', ', preg_replace('/^!KEYWORDS /', '', $line));
|
|
||||||
}
|
|
||||||
// 0 Name: <Filename>.dat
|
|
||||||
elseif (strpos($line, 'Name: ') === 0 && !isset($header['id'])) {
|
|
||||||
$model['id'] = preg_replace('/(^Name: )(.*)(.dat)/', '$2', $line);
|
|
||||||
}
|
|
||||||
// 0 Author: <Realname> [<Username>]
|
|
||||||
elseif (strpos($line, 'Author: ') === 0) {
|
|
||||||
$model['author'] = preg_replace('/^Author: /', '', $line);
|
|
||||||
}
|
|
||||||
// 0 !LDRAW_ORG Part|Subpart|Primitive|48_Primitive|Shortcut (optional qualifier(s)) ORIGINAL|UPDATE YYYY-RR
|
|
||||||
elseif (strpos($line, '!LDRAW_ORG ') === 0) {
|
|
||||||
$type = preg_replace('/(^!LDRAW_ORG )(.*)( UPDATE| ORIGINAL)(.*)/', '$2', $line);
|
|
||||||
|
|
||||||
$model['type'] = $type;
|
|
||||||
|
|
||||||
// Last modification date in format YYYY-RR
|
|
||||||
$date = preg_replace('/(^!LDRAW_ORG )(.*)( UPDATE | ORIGINAL )(.*)/', '$4', $line);
|
|
||||||
if (preg_match('/^[1-2][0-9]{3}-[0-9]{2}$/', $date)) {
|
|
||||||
$model['modified'] = \DateTime::createFromFormat('Y-m-d H:i:s', $date.'-01 00:00:00');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 0 !LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt | 0 !LICENSE Not redistributable : see NonCAreadme.txt
|
|
||||||
elseif (strpos($line, '!LICENSE ') === 0) {
|
|
||||||
$model['license'] = preg_replace('/(^!LICENSE )(.*) : (.*)$/', '$2', $line);
|
|
||||||
}
|
|
||||||
} elseif (strpos($line, '1 ') === 0) {
|
|
||||||
$id = strtolower($this->getReferencedModelNumber($line));
|
|
||||||
|
|
||||||
if (isset($model['subparts'][$id])) {
|
|
||||||
$model['subparts'][$id] = $model['subparts'][$id] + 1;
|
|
||||||
} else {
|
|
||||||
$model['subparts'][$id] = 1;
|
|
||||||
}
|
|
||||||
} elseif (!empty($line) && !in_array($line[0], ['2', '3', '4', '5'])) {
|
|
||||||
throw new ErrorParsingLineException($file,$line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->isSticker($model['name'], $model['id'])) {
|
|
||||||
$model['type'] = 'Sticker';
|
|
||||||
} elseif (count($model['subparts']) == 1 && in_array($model['type'], ['Part Alias', 'Shortcut Physical_Colour', 'Shortcut Alias', 'Part Physical_Colour'])) {
|
|
||||||
$model['parent'] = array_keys($model['subparts'])[0];
|
|
||||||
} elseif (($parent = $this->getPrintedModelParentNumber($model['id'])) && !in_array($model['type'], ['48_Primitive', '8_Primitive', 'Primitive', 'Subpart'])) {
|
|
||||||
$model['type'] = 'Printed';
|
|
||||||
$model['parent'] = $parent;
|
|
||||||
} elseif ($parent = $this->getObsoleteModelParentNumber($model['name'])) {
|
|
||||||
$model['type'] = 'Alias';
|
|
||||||
$model['parent'] = $parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose($handle);
|
|
||||||
|
|
||||||
return $model;
|
|
||||||
}
|
|
||||||
} catch (\Exception $exception) {
|
|
||||||
throw new ParseErrorException($file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new FileNotFoundException($file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get file reference from part line.
|
|
||||||
*
|
|
||||||
* Line type 1 is a sub-file reference. The generic format is:
|
|
||||||
* 1 <colour> x y z a b c d e f g h i <file>
|
|
||||||
*
|
|
||||||
* LDraw.org Standards: File Format 1.0.2 (http://www.ldraw.org/article/218.html)
|
|
||||||
*
|
|
||||||
* @param $line
|
|
||||||
*
|
|
||||||
* @return string|null Filename of referenced part
|
|
||||||
*/
|
|
||||||
public function getReferencedModelNumber($line)
|
|
||||||
{
|
|
||||||
$line = ($line);
|
|
||||||
|
|
||||||
if (preg_match('/^1(.*) (.*)\.dat$/', strtolower($line), $matches)) {
|
|
||||||
return str_replace('\\', DIRECTORY_SEPARATOR, $matches[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get printed part parent id.
|
|
||||||
*
|
|
||||||
* part name in format:
|
|
||||||
* nnnPxx, nnnnPxx, nnnnnPxx, nnnaPxx, nnnnaPxx (a = alpha, n= numeric, x = alphanumeric)
|
|
||||||
*
|
|
||||||
* http://www.ldraw.org/library/tracker/ref/numberfaq/
|
|
||||||
*
|
|
||||||
* @param $id
|
|
||||||
*
|
|
||||||
* @return string|null LDraw number of printed part parent
|
|
||||||
*/
|
|
||||||
public function getPrintedModelParentNumber($id)
|
|
||||||
{
|
|
||||||
if (preg_match('/(^.*)(p[0-9a-z]{2,3})$/', $id, $matches)) {
|
|
||||||
return $matches[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if part is shortcut part of stricker and part.
|
|
||||||
*
|
|
||||||
* part name in format:
|
|
||||||
* nnnDnn, nnnnDnn, nnnnnDnn (a = alpha, n= numeric, x = alphanumeric)
|
|
||||||
*
|
|
||||||
* http://www.ldraw.org/library/tracker/ref/numberfaq/
|
|
||||||
*
|
|
||||||
* @param $name
|
|
||||||
* @param $number
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isSticker($name, $number)
|
|
||||||
{
|
|
||||||
if (strpos($name, 'Sticker') === 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if in format n*Daa == sticker
|
|
||||||
return preg_match('/(^.*)(d[0-9]{2})$/', $number);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get parent of obsolete part kept for reference.
|
|
||||||
*
|
|
||||||
* part description in format:
|
|
||||||
* ~Moved to {new_number}
|
|
||||||
*
|
|
||||||
* http://www.ldraw.org/article/398.html (Appendix II (02-Oct-06))
|
|
||||||
*
|
|
||||||
* @param $name
|
|
||||||
*
|
|
||||||
* @return string|null Filename of referenced part
|
|
||||||
*/
|
|
||||||
public function getObsoleteModelParentNumber($name)
|
|
||||||
{
|
|
||||||
if (preg_match('/^(~Moved to )(.*)$/', $name, $matches)) {
|
|
||||||
return str_replace('\\', DIRECTORY_SEPARATOR, $matches[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user