1
0
mirror of https://github.com/ToxicCrack/PrintABrick.git synced 2025-05-29 10:10:25 -07:00

Improve Dat Parser

This commit is contained in:
David Hübner 2017-04-11 17:27:02 +02:00
parent ceda83225c
commit 814138aeb2

View File

@ -3,6 +3,7 @@
namespace AppBundle\Utils; namespace AppBundle\Utils;
use AppBundle\Exception\FileNotFoundException; use AppBundle\Exception\FileNotFoundException;
use AppBundle\Exception\ParseErrorException;
use League\Flysystem\File; use League\Flysystem\File;
use Symfony\Component\Asset\Exception\LogicException; use Symfony\Component\Asset\Exception\LogicException;
@ -25,12 +26,23 @@ class DatParser
* LDraw.org Standards: Official Library Header Specification (http://www.ldraw.org/article/398.html) * LDraw.org Standards: Official Library Header Specification (http://www.ldraw.org/article/398.html)
* *
* @return array * @return array
* @throws FileNotFoundException|ParseErrorException
*/ */
public function parse($file) public function parse($file)
{ {
$header = [];
if(file_exists($file)) { if(file_exists($file)) {
$model = [
'id' => null,
'name' => null,
'category' => null,
'keywords' => [],
'author' => null,
'modified' => null,
'type' => null,
'subparts' => [],
'parent' => null
];
try { try {
$handle = fopen($file, 'r'); $handle = fopen($file, 'r');
@ -47,86 +59,68 @@ class DatParser
// 0 <CategoryName> <PartDescription> // 0 <CategoryName> <PartDescription>
if (!$firstLine) { if (!$firstLine) {
$array = explode(' ', ltrim(trim($line, 2), '=_~')); $array = explode(' ', ltrim(trim($line, 2), '=_~'));
$header['category'] = isset($array[0]) ? $array[0] : ''; $model['category'] = isset($array[0]) ? $array[0] : '';
$header['name'] = preg_replace('/ {2,}/', ' ', ltrim($line, '=_')); $model['name'] = preg_replace('/ {2,}/', ' ', ltrim($line, '=_'));
$firstLine = true; $firstLine = true;
} // 0 !CATEGORY <CategoryName> } // 0 !CATEGORY <CategoryName>
elseif (strpos($line, '!CATEGORY ') === 0) { elseif (strpos($line, '!CATEGORY ') === 0) {
$header['category'] = trim(preg_replace('/^!CATEGORY /', '', $line)); $model['category'] = trim(preg_replace('/^!CATEGORY /', '', $line));
} // 0 !KEYWORDS <first keyword>, <second keyword>, ..., <last keyword> } // 0 !KEYWORDS <first keyword>, <second keyword>, ..., <last keyword>
elseif (strpos($line, '!KEYWORDS ') === 0) { elseif (strpos($line, '!KEYWORDS ') === 0) {
$header['keywords'] = explode(', ', preg_replace('/^!KEYWORDS /', '', $line)); $model['keywords'] = explode(', ', preg_replace('/^!KEYWORDS /', '', $line));
} // 0 Name: <Filename>.dat } // 0 Name: <Filename>.dat
elseif (strpos($line, 'Name: ') === 0) { elseif (strpos($line, 'Name: ') === 0 && !isset($header['id'])) {
if (!isset($header['id'])) { $model['id'] = preg_replace('/(^Name: )(.*)(.dat)/', '$2', $line);
$header['id'] = preg_replace('/(^Name: )(.*)(.dat)/', '$2', $line);
}
} // 0 Author: <Realname> [<Username>] } // 0 Author: <Realname> [<Username>]
elseif (strpos($line, 'Author: ') === 0) { elseif (strpos($line, 'Author: ') === 0) {
$header['author'] = preg_replace('/^Author: /', '', $line); $model['author'] = preg_replace('/^Author: /', '', $line);
} // 0 !LDRAW_ORG Part|Subpart|Primitive|48_Primitive|Shortcut (optional qualifier(s)) ORIGINAL|UPDATE YYYY-RR } // 0 !LDRAW_ORG Part|Subpart|Primitive|48_Primitive|Shortcut (optional qualifier(s)) ORIGINAL|UPDATE YYYY-RR
elseif (strpos($line, '!LDRAW_ORG ') === 0) { elseif (strpos($line, '!LDRAW_ORG ') === 0) {
$type = preg_replace('/(^!LDRAW_ORG )(.*)( UPDATE| ORIGINAL)(.*)/', '$2', $line); $type = preg_replace('/(^!LDRAW_ORG )(.*)( UPDATE| ORIGINAL)(.*)/', '$2', $line);
$header['type'] = $type; $model['type'] = $type;
// Last modification date in format YYYY-RR // Last modification date in format YYYY-RR
$date = preg_replace('/(^!LDRAW_ORG )(.*)( UPDATE | ORIGINAL )(.*)/', '$4', $line); $date = preg_replace('/(^!LDRAW_ORG )(.*)( UPDATE | ORIGINAL )(.*)/', '$4', $line);
if (preg_match('/^[1-2][0-9]{3}-[0-9]{2}$/', $date)) { if (preg_match('/^[1-2][0-9]{3}-[0-9]{2}$/', $date)) {
$header['modified'] = \DateTime::createFromFormat('Y-m-d H:i:s', $date . '-01 00:00:00'); $model['modified'] = \DateTime::createFromFormat('Y-m-d H:i:s', $date . '-01 00:00:00');
} else {
$header['modified'] = null;
} }
} }
} elseif (strpos($line, '1 ') === 0) { } elseif (strpos($line, '1 ') === 0) {
$id = $this->getAlias($line); $id = $this->getReferencedModelNumber($line);
if(isset($header['subparts'][$id])) { if(isset($model['subparts'][$id])) {
$header['subparts'][$id] = $header['subparts'][$id] + 1; $model['subparts'][$id] = $model['subparts'][$id] + 1;
} else { } else {
$header['subparts'][$id] = 1; $model['subparts'][$id] = 1;
} }
} }
} }
if ($this->isStickerShortcutPart($header['name'], $header['id'])) { if ($this->isSticker($model['name'], $model['id'])) {
$header['type'] = 'Sticker'; $model['type'] = 'Sticker';
} elseif (isset($header['subparts']) && count($header['subparts']) == 1 && in_array($header['type'], ['Part Alias', 'Shortcut Physical_Colour', 'Shortcut Alias', 'Part Physical_Colour'])) { } elseif (count($model['subparts']) == 1 && in_array($model['type'], ['Part Alias', 'Shortcut Physical_Colour', 'Shortcut Alias', 'Part Physical_Colour'])) {
$header['parent'] = array_keys($header['subparts'])[0]; $model['parent'] = array_keys($model['subparts'])[0];
$header['subparts'] = null; } elseif ($parent = $this->getPrintedModelParentNumber($model['id'])) {
} elseif ($parent = $this->getPrintedParentId($header['id'])) { $model['type'] = 'Printed';
$header['type'] = 'Printed'; $model['parent'] = $parent;
$header['subparts'] = null; } elseif ($parent = $this->getObsoleteModelParentNumber($model['name'])) {
$header['parent'] = $parent; $model['type'] = 'Alias';
} elseif ($parent = $this->getObsoleteParentId($header['name'])) { $model['parent'] = $parent;
$header['type'] = 'Alias'; } elseif (strpos($model['name'], '~') === 0 && $model['type'] != 'Alias') {
$header['subparts'] = null; $model['type'] = 'Obsolete/Subpart';
$header['parent'] = $parent;
} elseif (strpos($header['name'], '~') === 0 && $header['type'] != 'Alias') {
$header['type'] = 'Obsolete/Subpart';
} }
if(!isset($header['type'])) {
$header['type'] = 'Unknown';
}
if(!isset($header['modified'])) {
$header['modified'] = null;
}
// $header['name'] = ltrim($header['name'], '~');
fclose($handle); fclose($handle);
return $header; return $model;
} }
} catch (\Exception $exception) { } catch (\Exception $exception) {
dump($exception); throw new ParseErrorException($file);
throw new LogicException('Error parsing '.$file);
} }
} }
throw new LogicException('File not found '.$file); throw new FileNotFoundException($file);
} }
/** /**
@ -141,7 +135,7 @@ class DatParser
* *
* @return string|null Filename of referenced part * @return string|null Filename of referenced part
*/ */
public function getAlias($line) public function getReferencedModelNumber($line)
{ {
if(preg_match('/^1 16 0 0 0 -1 0 0 0 1 0 0 0 1 (.*)\.(dat|DAT)$/', $line, $matches)) if(preg_match('/^1 16 0 0 0 -1 0 0 0 1 0 0 0 1 (.*)\.(dat|DAT)$/', $line, $matches))
return null; return null;
@ -164,7 +158,7 @@ class DatParser
* *
* @return string|null LDraw number of printed part parent * @return string|null LDraw number of printed part parent
*/ */
public function getPrintedParentId($id) public function getPrintedModelParentNumber($id)
{ {
if (preg_match('/(^.*)(p[0-9a-z][0-9a-z][0-9a-z]{0,1})$/', $id, $matches)) { if (preg_match('/(^.*)(p[0-9a-z][0-9a-z][0-9a-z]{0,1})$/', $id, $matches)) {
return $matches[1]; return $matches[1];
@ -186,7 +180,7 @@ class DatParser
* *
* @return string|null LDraw number of printed part parent * @return string|null LDraw number of printed part parent
*/ */
public function isStickerShortcutPart($name, $number) public function isSticker($name, $number)
{ {
if (strpos($name, 'Sticker') === 0) { if (strpos($name, 'Sticker') === 0) {
return true; return true;
@ -208,7 +202,7 @@ class DatParser
* *
* @return string|null Filename of referenced part * @return string|null Filename of referenced part
*/ */
public function getObsoleteParentId($name) public function getObsoleteModelParentNumber($name)
{ {
if (preg_match('/^(~Moved to )(.*)$/', $name, $matches)) { if (preg_match('/^(~Moved to )(.*)$/', $name, $matches)) {
return $matches[2]; return $matches[2];