diff --git a/app/config/service/service.yml b/app/config/service/service.yml index 7ff2c69..3acdaf9 100644 --- a/app/config/service/service.yml +++ b/app/config/service/service.yml @@ -11,6 +11,10 @@ services: class: AppBundle\Service\LDViewService arguments: ['%ldview_bin%', '@oneup_flysystem.media_filesystem'] + service.zip: + class: AppBundle\Service\ZipService + arguments: ['@oneup_flysystem.media_filesystem', '@service.set'] + service.set: class: AppBundle\Service\SetService arguments: ['@repository.rebrickable.inventorypart'] \ No newline at end of file diff --git a/composer.json b/composer.json index 24ebd1e..3d0c899 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,8 @@ "oneup/flysystem-bundle": "^1.7", "knplabs/knp-paginator-bundle": "^2.5", "lexik/form-filter-bundle": "~5.0", - "liip/imagine-bundle": "^1.7" + "liip/imagine-bundle": "^1.7", + "maennchen/zipstream-php": "^0.4.0" }, "require-dev": { "sensio/generator-bundle": "^3.0", diff --git a/composer.lock b/composer.lock index 16f252a..3492149 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "3a905d4672661093643cd94176a46740", + "content-hash": "866b5e92a08d7be9fe2717af6aa79db8", "packages": [ { "name": "composer/ca-bundle", @@ -1803,6 +1803,58 @@ ], "time": "2017-03-02T20:18:55+00:00" }, + { + "name": "maennchen/zipstream-php", + "version": "v0.4.0", + "source": { + "type": "git", + "url": "https://github.com/maennchen/ZipStream-PHP.git", + "reference": "b1fad778ef53873cb79ed7998a6515a967955746" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/b1fad778ef53873cb79ed7998a6515a967955746", + "reference": "b1fad778ef53873cb79ed7998a6515a967955746", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">= 5.3" + }, + "require-dev": { + "phpunit/phpunit": "4.3.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "ZipStream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paul Duncan", + "email": "pabs@pablotron.org" + }, + { + "name": "Jesse Donat", + "email": "donatj@gmail.com" + }, + { + "name": "Jonatan Männchen", + "email": "jonatan@maennchen.ch" + } + ], + "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.", + "keywords": [ + "stream", + "zip" + ], + "time": "2016-09-13T10:19:09+00:00" + }, { "name": "monolog/monolog", "version": "1.22.1", diff --git a/src/AppBundle/Service/ZipService.php b/src/AppBundle/Service/ZipService.php index 7be9188..a4d61ab 100644 --- a/src/AppBundle/Service/ZipService.php +++ b/src/AppBundle/Service/ZipService.php @@ -2,7 +2,123 @@ namespace AppBundle\Service; +use AppBundle\Entity\LDraw\Model; +use AppBundle\Entity\Rebrickable\Set; +use League\Flysystem\Filesystem; +use ZipStream\ZipStream; + class ZipService { + /** @var ZipStream */ + private $archive; -} \ No newline at end of file + /** @var Filesystem */ + private $mediaFilesystem; + + /** @var SetService */ + private $setService; + + /** + * ZipService constructor. + * + * @param $mediaFilesystem + * @param $setService + */ + public function __construct($mediaFilesystem, $setService) + { + $this->mediaFilesystem = $mediaFilesystem; + $this->setService = $setService; + } + + public function createFromSet(Set $set, $sorted = false) + { + $sort = $sorted ? 'sorted' : 'unsorted'; + + $filename = "set_{$set->getNumber()}_{$set->getName()}({$sort}).zip"; + + // Initialize zip stream + $this->archive = new ZipStream($filename); + + if ($sorted) { + $this->addSet($set); + } else { + $this->addSetGroupedByColor($set); + } + + $this->archive->finish(); + + return $this->archive; + } + + public function createFromModel(Model $model, $subparts = false) + { + $filename = "model_{$model->getNumber()}.zip"; + + // Initialize zip stream + $this->archive = new ZipStream($filename); + + $this->addModel($model); + + $this->archive->finish(); + + return $this->archive; + } + + /** + * Add stl files of models used in set into zip grouped by color. + * + * @param Set $set + * @param bool $spare If true - add only spare parts, false - add only regular parts, null - add all parts + */ + public function addSetGroupedByColor(Set $set, $spare = null) + { + $colors = $this->setService->getModelsGroupedByColor($set, $spare); + + foreach ($colors as $colorArray) { + $models = $colorArray['models']; + $color = $colorArray['color']; + foreach ($models as $modelArray) { + $model = $modelArray['model']; + $quantity = $modelArray['quantity']; + + $filename = "{$color->getName()}/{$model->getNumber()}_({$quantity}x).stl"; + + $this->archive->addFile($filename, $this->mediaFilesystem->read($model->getPath())); + } + } + } + + /** + * Add stl files used in set into zip. + * + * @param Set $set + * @param bool $spare If true - add only spare parts, false - add only regular parts, null - add all parts + */ + public function addSet(Set $set, $spare = null) + { + $models = $this->setService->getModels($set, $spare); + + foreach ($models as $number => $array) { + $quantity = $array['quantity']; + $filename = $number."_({$quantity}x).stl"; + + $this->archive->addFile($filename, $this->mediaFilesystem->read($array['model']->getPath())); + } + } + + public function addModel(Model $model, $count = 1, $folder = '') + { + $filename = $folder.$model->getNumber()."_({$count}x).stl"; + + $this->archive->addFile($filename, $this->mediaFilesystem->read($model->getPath())); + + foreach ($model->getSubparts() as $subpart) { + $this->addModel($subpart->getSubpart(), $subpart->getCount(), $folder.$model->getNumber().'_subparts/'); + } + } + + // TODO add licence file and information to zip file + public function addLicence() + { + } +}