1
0
mirror of https://github.com/ToxicCrack/PrintABrick.git synced 2025-05-16 20:30:09 -07:00

Refactor business logic, Autowire dependencies

This commit is contained in:
Unknown 2017-06-07 17:21:53 +02:00
parent b301aebcbd
commit d66955d62d
58 changed files with 966 additions and 682 deletions

View File

@ -8,6 +8,8 @@
.link { .link {
padding-left: 30px; padding-left: 30px;
position: relative; position: relative;
display: inline-block;
margin: 0.2em 1em;
} }
.link:before { .link:before {

View File

@ -2,12 +2,12 @@ page:
home: Homepage home: Homepage
model: model:
index: Bricks index: Bricks
detail: %value% detail: "%value%"
set: set:
index: Sets index: Sets
detail: %value% detail: "%value%"
part: part:
index: Parts index: Parts
detail: %value% detail: "%value%"
search: "Search: \"%value%\"" search: "Search: \"%value%\""
colors: Colors colors: Colors

View File

@ -11,7 +11,7 @@ set:
models: models:
text: | text: |
This set inventory has been obtained from Rebrickable. This set inventory has been obtained from Rebrickable.
According to the Brickset, this set has %brickset% parts. The inventory from Rebrickable contains %rebrickable% parts. According to the Brickset, this set has '%brickset%' parts. The inventory from Rebrickable contains %rebrickable% parts.
rebrickable: rebrickable:
credit: | credit: |
This set inventory and model images has been obtained from <a href="https://rebrickable.com/" title="Rebrickable">Rebrickable</a>. This set inventory and model images has been obtained from <a href="https://rebrickable.com/" title="Rebrickable">Rebrickable</a>.
@ -137,4 +137,4 @@ part:
form: form:
search.submit: Search search.submit: Search
meta.description: Web catalogue of LEGO<sup>®</sup> parts for 3D printing meta.description: "Web catalogue of LEGO<sup>®</sup> parts for 3D printing"

View File

@ -106,4 +106,29 @@
</main> </main>
{% include 'footer.html.twig' %} {% include 'footer.html.twig' %}
</div> </div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<!-- Go to www.addthis.com/dashboard to customize your tools -->
<script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-593560849f04e2fa"></script>
<script type="text/javascript">
$(document).ajaxComplete(function () {
$("#results").on( "click", ".pagination a", function (e){
e.preventDefault();
var page = $(this).attr("href"); //get page number from link
$.ajax({
type: 'GET',
url: page,
dataType: 'json',
success: function (data) {
$('#results').replaceWith(data);
}
});
});
});
</script>
{% endblock %} {% endblock %}

View File

@ -105,7 +105,7 @@
{% endif %} {% endif %}
<span> <span>
{% set label = item.label|trans( {% set label = item.label|trans(
item.getExtra('translation_params', {}), item.getExtra('translatinon_params', {}),
item.getExtra('translation_domain', 'menu') item.getExtra('translation_domain', 'menu')
) %} ) %}
{% if options.allow_safe_labels and item.getExtra('safe_label', false) %} {% if options.allow_safe_labels and item.getExtra('safe_label', false) %}

View File

@ -25,6 +25,7 @@
</div> </div>
<div class="column six wide"> <div class="column six wide">
<div class="item-info ui"> <div class="item-info ui">
<div class="addthis_inline_share_toolbox"></div>
<table class="ui very basic table"> <table class="ui very basic table">
<tr> <tr>
<td>{{ 'model.id' | trans }}</td> <td>{{ 'model.id' | trans }}</td>
@ -41,9 +42,6 @@
<tr> <tr>
<td>{{ 'model.author' | trans }}</td><td>{{ model.author.name }}</td> <td>{{ 'model.author' | trans }}</td><td>{{ model.author.name }}</td>
</tr> </tr>
<tr>
<td>{{ 'model.set.count' | trans }}</td><td>{{ sets|length }}</td>
</tr>
<tr> <tr>
<td>{{ 'model.license' | trans }}</td> <td>{{ 'model.license' | trans }}</td>
<td> <td>
@ -80,39 +78,57 @@
<div class="ui vertical segment"> <div class="ui vertical segment">
<div class="ui tabular pointing secondary menu stackable"> <div class="ui tabular pointing secondary menu stackable">
<div class="container ui"> <div class="container ui">
<a class="item active" data-tab="subparts">{{ 'model.subparts' | trans }} ({{ subparts|length }})</a> <a class="item active" data-tab="related">{{ 'model.related' | trans }}</a>
<a class="item" data-tab="related">{{ 'model.related' | trans }} ({{ related|length }})</a> <a class="item" data-tab="sets">{{ 'model.sets' | trans }}</a>
<a class="item" data-tab="parents">{{ 'model.parents' | trans }} ({{ model.parents|length }})</a> {#<a class="item" data-tab="parents">{{ 'model.parents' | trans }} ({{ model.parents|length }})</a>#}
</div> </div>
</div> </div>
<div class="container ui"> <div class="container ui">
<div class="ui tab active" data-tab="subparts"> <div class="ui tab active" data-tab="related">
<div class="ui grid doubling ten column row parts"> <div class="segment vertical ui">
{% for subpart in subparts %} <h3 class="header">Submodels</h3>
{{ blocks.model(subpart['model'], subpart['quantity']) }} <div class="ui grid doubling ten column row parts">
{% endfor %} {% for subpart in submodels %}
{{ blocks.model(subpart['model'], subpart['quantity']) }}
{% else %}
<div class="empty"></div>
{% endfor %}
</div>
</div> </div>
<div class="segment vertical ui">
<h3 class="header">Siblings</h3>
<div class="ui grid doubling ten column row parts">
{% for model in siblings %}
{{ blocks.model(model) }}
{% else %}
<div class="empty"></div>
{% endfor %}
</div>
</div>
<div class="segment vertical ui">
<h3 class="header">Parents</h3>
<div class="ui grid doubling ten column row parts">
{% for subpart in model.parents %}
{{ blocks.model(subpart.parent) }}
{% else %}
<div class="empty"></div>
{% endfor %}
</div>
</div>
</div> </div>
<div class="ui tab" data-tab="related"> <div class="ui tab ajax-load" data-tab="sets" data-src="{{ path('model_sets', { id: model.id, page: app.request.get('page') }) }}">
<div class="ui grid doubling ten column row parts"> <div class="ui active centered inline loader"></div>
{% for model in related %}
{{ blocks.model(model) }}
{% endfor %}
</div>
</div> </div>
<div class="ui tab" data-tab="parents">
<div class="ui grid doubling ten column row parts">
{% for subpart in model.parents %}
{{ blocks.model(subpart.parent) }}
{% endfor %}
</div>
</div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
{% block javascripts %} {% block javascripts %}
@ -120,6 +136,7 @@
<script type="text/javascript" src="{{ fileTimestamp(asset('resources/js/three.js')) }}"></script> <script type="text/javascript" src="{{ fileTimestamp(asset('resources/js/three.js')) }}"></script>
<script type="text/javascript" src="{{ fileTimestamp(asset('resources/js/OrbitControls.js')) }}"></script> <script type="text/javascript" src="{{ fileTimestamp(asset('resources/js/OrbitControls.js')) }}"></script>
<script type="text/javascript"> <script type="text/javascript">
window.onload = function() { window.onload = function() {
$('#model-viewer').ModelViewer('{{ path('media_file', {'path': model.path }) }}'); $('#model-viewer').ModelViewer('{{ path('media_file', {'path': model.path }) }}');

View File

@ -0,0 +1,42 @@
{% import 'macros/blocks.html.twig' as blocks %}
{% import 'macros/elements.html.twig' as elements %}
{% block content %}
<div id="results">
<div class="ui header segment basic sort">
<div class="ui grid stackable">
<div class="left floated left aligned twelve wide column">
<div class="ui text menu">
<div class="header item">Sort By</div>
{{ knp_pagination_sortable(sets, 'Number', ['s.id']) }}
{{ knp_pagination_sortable(sets, 'Year', ['s.year']) }}
{{ knp_pagination_sortable(sets, 'Name', ['s.name']) }}
{{ knp_pagination_sortable(sets, 'Parts', ['s.partCount']) }}
</div>
</div>
<div class="right floated right aligned four wide column">
<div class="ui text right floated menu">
<div class="header item">Showing</div>
<span class="item">{{ sets.getTotalItemCount }}</span>
</div>
</div>
</div>
</div>
<div class="ui segment basic">
{% block sets %}
<div class="ui eight column doubling grid sets">
{% for set in sets %}
{{ blocks.set(set) }}
{% else %}
{{ blocks.empty('empty.search.title' | trans ) }}
{% endfor %}
</div>
{% endblock %}
</div>
<div class="ui segment basic">
{{ knp_pagination_render(sets) }}
</div>
</div>
{% endblock %}

View File

@ -18,64 +18,69 @@
{% block content %} {% block content %}
<div class="ui vertical segment grey inverted tertiary"> <div class="ui vertical segment grey inverted tertiary">
<div class="ui container stackable grid"> <div class="ui container stackable grid">
<div class="row"> <div class="column ten wide">
<div class="column ten wide"> <div id="model-viewer" class="model-container">
<div id="model-viewer" class="model-container"> {{ blocks.partImage(part.id,'part_large') }}
{{ blocks.partImage(part.id,'part_large') }}
</div>
</div> </div>
<div class="column six wide"> </div>
<div class="item-info ui"> <div class="column six wide">
<table class="ui very basic table"> <div class="item-info ui">
<table class="ui very basic table">
<tr>
<td>{{ 'part.id' | trans }}</td><td><h2>{{ part.id}}</h2></td>
</tr>
<tr>
<td>{{ 'part.name' | trans }}</td><td>{{ part.name}}</td>
</tr>
<tr>
<td>{{ 'part.category' | trans }}</td><td>{{ part.category ? part.category.name }}</td>
</tr>
<tr>
<td>{{ 'part.model' | trans }}</td>
<td>
{% if part.model %}
<a href="{{ url('model_detail', {'id': part.model.id})}}">{{ part.model.id }}</a>
{% endif %}
</td>
</tr>
{% if apiPart %}
<tr> <tr>
<td>{{ 'part.id' | trans }}</td><td><h2>{{ part.id}}</h2></td> <td>{{ 'part.alternates' | trans }}</td>
</tr>
<tr>
<td>{{ 'part.name' | trans }}</td><td>{{ part.name}}</td>
</tr>
<tr>
<td>{{ 'part.category' | trans }}</td><td>{{ part.category ? part.category.name }}</td>
</tr>
<tr>
<td>{{ 'part.model' | trans }}</td>
<td> <td>
{% if part.model %} {% for alternate in apiPart.alternates %}
<a href="{{ url('model_detail', {'id': part.model.id})}}">{{ part.model.id }}</a> <a href="{{ url('part_detail', {'id': alternate})}}">{{ alternate }}</a>
{% endif %} {% endfor %}
</td> </td>
</tr> </tr>
{% if apiPart %} <tr>
<tr> <td>{{ 'part.molds' | trans }}</td>
<td>{{ 'part.alternates' | trans }}</td> <td>
<td> {% for mold in apiPart.molds %}
{% for alternate in apiPart.alternates %} <a href="{{ url('part_detail', {'id': mold})}}">{{ mold }}</a>
<a href="{{ url('part_detail', {'id': alternate})}}">{{ alternate }}</a> {% endfor %}
{% endfor %} </td>
</td> </tr>
</tr> <tr>
<tr> <td></td>
<td>{{ 'part.molds' | trans }}</td> <td><a class="rebrickable link" href="{{ apiPart.url }}">Rebrickable</a></td>
<td> </tr>
{% for mold in apiPart.molds %}
<a href="{{ url('part_detail', {'id': mold})}}">{{ mold }}</a>
{% endfor %}
</td>
</tr>
<tr>
<td></td>
<td><a class="rebrickable link" href="{{ apiPart.url }}">Rebrickable</a></td>
</tr>
{% endif %}
</table>
{% if not part.model %}
<a class="ui disabled fluid primary button"><i class="download icon"></i> {{ 'model.empty'|trans }}</a>
{% else %}
<a class="ui fluid primary button" href="{{ path('model_zip', {id: part.model.id}) }}"><i class="download icon"></i> {{ 'model.download'|trans }}</a>
{% endif %} {% endif %}
</div> </table>
{% if not part.model %}
<a class="ui disabled fluid primary button"><i class="download icon"></i> {{ 'model.empty'|trans }}</a>
{% else %}
<a class="ui fluid primary button" href="{{ path('model_zip', {id: part.model.id}) }}"><i class="download icon"></i> {{ 'model.download'|trans }}</a>
{% endif %}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="ui vertical segment">
<div class="container ui">
<div class="ui ajax-load" data-tab="sets" data-src="{{ path('part_sets', { id: part.id, page: app.request.get('page') }) }}">
<div class="ui active centered inline loader"></div>
</div>
</div>
</div>
{% endblock %} {% endblock %}

View File

@ -59,20 +59,18 @@
{{ brset.rating | number_format(1, '.', ',') }} / 5 {{ brset.rating | number_format(1, '.', ',') }} / 5
</td> </td>
</tr> </tr>
<tr>
<td></td>
<td>
<a class="brickset link" href="{{ brset.bricksetURL }}">Brickset</a>
</td>
</tr>
{% endif %} {% endif %}
<tr> <tr>
<td></td> <td></td>
<td> <td>
<a class="rebrickable link" href="http://rebrickable.com/sets/{{ set ? set.id }}">Rebrickable</a> <a class="rebrickable link" href="http://rebrickable.com/sets/{{ set ? set.id }}">Rebrickable</a>
{% if brset %}
<a class="brickset link" href="{{ brset.bricksetURL }}">Brickset</a>
{% endif %}
</td> </td>
</tr> </tr>
</table> </table>
<div class="addthis_inline_share_toolbox"></div>
</div> </div>
</div> </div>
</div> </div>
@ -111,4 +109,4 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -1,14 +0,0 @@
services:
api.client.brickset:
class: AppBundle\Api\Client\Brickset\Brickset
arguments: ['%brickset_apikey%']
api.client.rebrickable:
class: AppBundle\Api\Client\Rebrickable\Rebrickable_v3
arguments: ['%rebrickable_apikey%']
api.manager.brickset:
class: AppBundle\Api\Manager\BricksetManager
arguments: ['@api.client.brickset', '@app.brickset.cache_provider']
api.manager.rebrickable:
class: AppBundle\Api\Manager\RebrickableManager
arguments: ['@api.client.rebrickable']

View File

@ -1,21 +0,0 @@
services:
form.filter.brickset:
class: AppBundle\Form\FilterSetType
arguments: ['@api.manager.brickset']
tags:
- { name: form.type }
form.search.model:
class: AppBundle\Form\Search\ModelSearchType
arguments:
- '@repository.ldraw.category'
tags:
- { name: form.type }
form.search.set:
class: AppBundle\Form\Search\SetSearchType
arguments:
- '@repository.rebrickable.theme'
- '@repository.rebrickable.set'
tags:
- { name: form.type }

View File

@ -0,0 +1,29 @@
services:
# service.set: '@AppBundle\Service\SetService'
# service.zip: '@AppBundle\Service\ZipService'
# service.model: '@AppBundle\Service\ModelService'
# service.stl.fixer: '@AppBundle\Service\Stl\StlFixerService'
# service.stl.converter: '@AppBundle\Service\Stl\StlConverterService'
# service.stl.renderer: '@AppBundle\Service\Stl\StlRendererService'
#
# app.part_image_loader: '@AppBundle\Imagine\PartImageLoader'
# app.set_image_loader: '@AppBundle\Imagine\SetImageLoader'
#
# app.transformer.format: '@AppBundle\Transformer\FormatTransformer'
# app.relation.mapper: '@AppBundle\Util\RelationMapper'
#
service.loader.base: '@AppBundle\Service\Loader\BaseLoader'
service.loader.rebrickable: '@AppBundle\Service\Loader\RebrickableLoader'
service.loader.model: '@AppBundle\Service\Loader\ModelLoader'
service.loader.relation: '@AppBundle\Service\Loader\RelationLoader'
service.loader.image: '@AppBundle\Service\Loader\ImageLoader'
# form.search.model: '@AppBundle\Form\Search\ModelSearchType'
# form.search.set: '@AppBundle\Form\Search\SetSearchType'
#
# api.manager.rebrickable: '@AppBundle\Api\Manager\RebrickableManager'
# api.manager.brickset: '@AppBundle\Api\Manager\BricksetManager'
# api.client.rebrickable: '@AppBundle\Api\Client\Rebrickable\RebrickableClient'
# api.client.brickset: '@AppBundle\Api\Client\Brickset\BricksetClient'
# knp_menu.factory: Knp\Menu\FactoryInterface

View File

@ -1,26 +0,0 @@
services:
service.loader.base:
abstract: true
class: AppBundle\Service\Loader\BaseLoader
calls:
- [setArguments, ['@doctrine.orm.entity_manager', '@monolog.logger.loader', '@app.transformer.format']]
service.loader.rebrickable:
class: AppBundle\Service\Loader\RebrickableLoader
arguments: ['%app.rebrickable_downloads_url%']
parent: service.loader.base
service.loader.model:
class: AppBundle\Service\Loader\ModelLoader
arguments: ['@service.stl.converter', '@app.relation.mapper']
parent: service.loader.base
service.loader.relation:
class: AppBundle\Service\Loader\RelationLoader
arguments: ['@app.relation.mapper','@repository.ldraw.model', '@repository.rebrickable.part']
parent: service.loader.base
service.loader.image:
class: AppBundle\Service\Loader\ImageLoader
arguments: ['@oneup_flysystem.media_filesystem', '%app.rebrickable_downloads_url%','@service.stl.renderer']
parent: service.loader.base

View File

@ -1,6 +1 @@
services: services:
menu.builder.main:
class: AppBundle\Menu\Builder
arguments: ['@knp_menu.factory', '@request_stack']
tags:
- { name: knp_menu.menu_builder, method: mainMenu, alias: mainMenu }

View File

@ -1,91 +0,0 @@
services:
repository.color:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine", getRepository]
arguments:
- AppBundle\Entity\Color
repository.ldraw.keyword:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine", getRepository]
arguments:
- AppBundle\Entity\LDraw\Keyword
repository.ldraw.category:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine", getRepository]
arguments:
- AppBundle\Entity\LDraw\Category
repository.ldraw.model:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine", getRepository]
arguments:
- AppBundle\Entity\LDraw\Model
repository.ldraw.part:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine", getRepository]
arguments:
- AppBundle\Entity\LDraw\Part
repository.ldraw.type:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine", getRepository]
arguments:
- AppBundle\Entity\LDraw\Type
repository.ldraw.subpart:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine", getRepository]
arguments:
- AppBundle\Entity\LDraw\Subpart
repository.ldraw.alias:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine", getRepository]
arguments:
- AppBundle\Entity\LDraw\Alias
repository.ldraw.author:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine", getRepository]
arguments:
- AppBundle\Entity\LDraw\Author
repository.rebrickable.category:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine", getRepository]
arguments:
- AppBundle\Entity\Rebrickable\Category
repository.rebrickable.inventory:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine", getRepository]
arguments:
- AppBundle\Entity\Rebrickable\Inventory
repository.rebrickable.inventoryPart:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine", getRepository]
arguments:
- AppBundle\Entity\Rebrickable\Inventory_Part
repository.rebrickable.part:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine", getRepository]
arguments:
- AppBundle\Entity\Rebrickable\Part
repository.rebrickable.set:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine", getRepository]
arguments:
- AppBundle\Entity\Rebrickable\Set
repository.rebrickable.theme:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine", getRepository]
arguments:
- AppBundle\Entity\Rebrickable\Theme

View File

@ -1,38 +0,0 @@
services:
app.brickset.cache_provider:
class: Doctrine\Common\Cache\PhpFileCache
arguments: ["%kernel.cache_dir%/brickset", ".cache.php"]
service.stl.renderer:
class: AppBundle\Service\Stl\StlRendererService
arguments: ['%kernel.root_dir%/Resources/povray_layout/layout.tmpl', '%povray_bin%','%stl2pov_bin%']
service.stl.converter:
class: AppBundle\Service\Stl\StlConverterService
arguments: ['%ldview_bin%', '@oneup_flysystem.media_filesystem', '@service.stl.fixer']
service.stl.fixer:
class: AppBundle\Service\Stl\StlFixerService
arguments: ['%admesh_bin%']
service.zip:
class: AppBundle\Service\ZipService
arguments: ['@oneup_flysystem.media_filesystem', '@service.set', '@service.model']
service.set:
class: AppBundle\Service\SetService
arguments: ['@repository.rebrickable.inventoryPart']
service.model:
class: AppBundle\Service\ModelService
app.part_image_loader:
class: AppBundle\Imagine\PartImageLoader
arguments: ['@api.manager.rebrickable', '@oneup_flysystem.media_filesystem']
tags:
- { name: liip_imagine.binary.loader, loader: part_image_loader }
app.set_image_loader:
class: AppBundle\Imagine\SetImageLoader
arguments: ['@api.manager.brickset', '@oneup_flysystem.media_filesystem']
tags:
- { name: liip_imagine.binary.loader, loader: set_image_loader }

View File

@ -1,16 +0,0 @@
services:
app.transformer.format:
class: AppBundle\Transformer\FormatTransformer
app.relation.mapper:
class: AppBundle\Util\RelationMapper
calls:
- [ loadResource, ['%kernel.root_dir%/Resources/relations/part_model.yml', 'part_model']]
- [ loadResource, ['%kernel.root_dir%/Resources/relations/alias_model.yml', 'alias_model']]
app.twig_extension:
class: AppBundle\Twig\AppExtension
public: false
arguments: ['@app.transformer.format']
tags:
- { name: twig.extension }

View File

@ -1,8 +1,92 @@
imports: imports:
- { resource: service/repository.yml } - { resource: service/legacy_aliases.yml }
- { resource: service/api.yml } - { resource: service/menu.yml }
- { resource: service/loader.yml }
- { resource: service/util.yml } services:
- { resource: service/service.yml } # default configuration for services in *this* file
- { resource: service/form.yml } _defaults:
- { resource: service/menu.yml } # automatically injects dependencies in your services
autowire: true
# automatically registers your services as commands, event subscribers, etc.
autoconfigure: true
public: false
# makes classes in src/AppBundle available to be used as services
# this creates a service per class whose id is the fully-qualified class name
AppBundle\:
resource: '../../src/AppBundle/*'
exclude: '../../src/AppBundle/{Entity,Repository,Exception,Api}'
# controllers are imported separately to make sure they're public
# and have a tag that allows actions to type-hint services
AppBundle\Controller\:
resource: '../../src/AppBundle/Controller'
public: true
tags: ['controller.service_arguments']
app.brickset.cache_provider:
class: Doctrine\Common\Cache\PhpFileCache
arguments: ["%kernel.cache_dir%/brickset", ".cache.php"]
AppBundle\Service\Stl\StlRendererService:
arguments:
$layout: '%kernel.root_dir%/Resources/povray_layout/layout.tmpl'
$povray: '%povray_bin%'
$stl2pov: '%stl2pov_bin%'
AppBundle\Service\Stl\StlConverterService:
arguments:
$ldview: '%ldview_bin%'
AppBundle\Service\Stl\StlFixerService:
arguments:
$ADMesh: '%admesh_bin%'
AppBundle\Api\Client\Brickset\BricksetClient:
arguments:
$apiKey: '%brickset_apikey%'
AppBundle\Api\Client\Rebrickable\RebrickableClient:
arguments:
$apiKey: '%rebrickable_apikey%'
AppBundle\Api\Manager\RebrickableManager: ~
AppBundle\Api\Manager\BricksetManager:
arguments:
$cache: '@app.brickset.cache_provider'
AppBundle\Imagine\PartImageLoader:
tags:
- { name: liip_imagine.binary.loader, loader: part_image_loader }
AppBundle\Imagine\SetImageLoader:
tags:
- { name: liip_imagine.binary.loader, loader: set_image_loader }
AppBundle\Service\Loader\BaseLoader:
abstract: true
AppBundle\Service\Loader\RebrickableLoader:
arguments:
$rebrickableDownloadUrl: '%app.rebrickable_downloads_url%'
AppBundle\Service\Loader\ImageLoader:
arguments:
$rebrickableDownloadUrl: '%app.rebrickable_downloads_url%'
AppBundle\Util\RelationMapper:
calls:
- [ loadResource, ['%kernel.root_dir%/Resources/relations/part_model.yml', 'part_model']]
- [ loadResource, ['%kernel.root_dir%/Resources/relations/alias_model.yml', 'alias_model']]
menu.builder.main:
class: AppBundle\Menu\Builder
arguments: ['@knp_menu.factory', '@request_stack']
public: true
tags:
- { name: knp_menu.menu_builder, method: mainMenu, alias: mainMenu }
AppBundle\Twig\AppExtension:
tags:
- { name: twig.extension }

View File

@ -13,7 +13,7 @@ use AppBundle\Api\Exception\ApiException;
use AppBundle\Api\Exception\AuthenticationFailedException; use AppBundle\Api\Exception\AuthenticationFailedException;
use AppBundle\Api\Exception\CallFailedException; use AppBundle\Api\Exception\CallFailedException;
class Brickset class BricksetClient
{ {
const WSDL = 'https://brickset.com/api/v2.asmx?WSDL'; const WSDL = 'https://brickset.com/api/v2.asmx?WSDL';
@ -40,14 +40,16 @@ class Brickset
]; ];
/** /**
* BricksetClient constructor.
*
* @param string $apikey Brickset API key * @param string $apikey Brickset API key
* @param array $options A array of config values * @param array $options A array of config values
* *
* @throws ApiException * @throws ApiException
*/ */
public function __construct($apikey, array $options = []) public function __construct($apiKey, array $options = [])
{ {
$this->apiKey = $apikey; $this->apiKey = $apiKey;
$this->options['cache_wsdl'] = WSDL_CACHE_NONE; $this->options['cache_wsdl'] = WSDL_CACHE_NONE;
$this->options['exceptions'] = true; $this->options['exceptions'] = true;
@ -59,15 +61,16 @@ class Brickset
} }
} }
/** /**
* Get or create new SoapClient * Get or create new SoapClient.
*
* @throws ApiException
* *
* @return \SoapClient * @return \SoapClient
* @throws ApiException
*/ */
private function getSoapClient() { private function getSoapClient()
if(!$this->soapClient) { {
if (!$this->soapClient) {
try { try {
$this->soapClient = new \SoapClient(self::WSDL, $this->options); $this->soapClient = new \SoapClient(self::WSDL, $this->options);
} catch (\SoapFault $exception) { } catch (\SoapFault $exception) {
@ -80,6 +83,7 @@ class Brickset
throw new ApiException(ApiException::BRICKSET); throw new ApiException(ApiException::BRICKSET);
} }
} }
return $this->soapClient; return $this->soapClient;
} }

View File

@ -10,7 +10,7 @@ use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException; use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Exception\ConnectException;
class Rebrickable_v3 class RebrickableClient
{ {
const BASE_URI = 'https://rebrickable.com/api/v3/'; const BASE_URI = 'https://rebrickable.com/api/v3/';
@ -26,6 +26,8 @@ class Rebrickable_v3
/** /**
* RebrickableAPI constructor. * RebrickableAPI constructor.
*
* @param string $apiKey
*/ */
public function __construct($apiKey) public function __construct($apiKey)
{ {

View File

@ -2,13 +2,13 @@
namespace AppBundle\Api\Manager; namespace AppBundle\Api\Manager;
use AppBundle\Api\Client\Brickset\Brickset; use AppBundle\Api\Client\Brickset\BricksetClient;
use Doctrine\Common\Cache\CacheProvider; use Doctrine\Common\Cache\CacheProvider;
class BricksetManager class BricksetManager
{ {
/** /**
* @var Brickset * @var BricksetClient
*/ */
private $bricksetClient; private $bricksetClient;
@ -19,10 +19,10 @@ class BricksetManager
/** /**
* BricksetManager constructor. * BricksetManager constructor.
* *
* @param Brickset $bricksetClient * @param BricksetClient $bricksetClient
* @param CacheProvider $cache * @param CacheProvider $cache
*/ */
public function __construct(Brickset $bricksetClient, CacheProvider $cache) public function __construct(BricksetClient $bricksetClient, CacheProvider $cache)
{ {
$this->bricksetClient = $bricksetClient; $this->bricksetClient = $bricksetClient;
$this->cache = $cache; $this->cache = $cache;

View File

@ -8,7 +8,7 @@ use AppBundle\Api\Client\Rebrickable\Entity\Part;
use AppBundle\Api\Client\Rebrickable\Entity\PartCategory; use AppBundle\Api\Client\Rebrickable\Entity\PartCategory;
use AppBundle\Api\Client\Rebrickable\Entity\Set; use AppBundle\Api\Client\Rebrickable\Entity\Set;
use AppBundle\Api\Client\Rebrickable\Entity\Theme; use AppBundle\Api\Client\Rebrickable\Entity\Theme;
use AppBundle\Api\Client\Rebrickable\Rebrickable_v3; use AppBundle\Api\Client\Rebrickable\RebrickableClient;
use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
@ -19,7 +19,7 @@ class RebrickableManager
const FORMAT = 'json'; const FORMAT = 'json';
/** /**
* @var Rebrickable_v3 * @var RebrickableClient
*/ */
private $rebrickableClient; private $rebrickableClient;
@ -31,9 +31,9 @@ class RebrickableManager
/** /**
* RebrickableManager constructor. * RebrickableManager constructor.
* *
* @param Rebrickable_v3 $rebrickableClient * @param RebrickableClient $rebrickableClient
*/ */
public function __construct(Rebrickable_v3 $rebrickableClient) public function __construct(RebrickableClient $rebrickableClient)
{ {
$this->rebrickableClient = $rebrickableClient; $this->rebrickableClient = $rebrickableClient;
$this->serializer = $this->initSerializer(); $this->serializer = $this->initSerializer();
@ -176,7 +176,6 @@ class RebrickableManager
$response = $this->rebrickableClient->call('GET', 'lego/sets/'.$setId.'/parts', $options); $response = $this->rebrickableClient->call('GET', 'lego/sets/'.$setId.'/parts', $options);
$data = json_decode($response, true)['results']; $data = json_decode($response, true)['results'];
return $this->serializer->denormalize($data, Part::class.'[]', self::FORMAT); return $this->serializer->denormalize($data, Part::class.'[]', self::FORMAT);
} }
} }

View File

@ -2,6 +2,7 @@
namespace AppBundle\Command; namespace AppBundle\Command;
use AppBundle\Service\Loader\ImageLoader;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
@ -10,6 +11,18 @@ use Symfony\Component\Console\Output\OutputInterface;
class LoadImagesCommand extends ContainerAwareCommand class LoadImagesCommand extends ContainerAwareCommand
{ {
private $imageLoader;
/**
* LoadImagesCommand constructor.
*/
public function __construct($name = null, ImageLoader $imageLoader)
{
$this->imageLoader = $imageLoader;
parent::__construct($name);
}
protected function configure() protected function configure()
{ {
$this $this
@ -27,17 +40,16 @@ class LoadImagesCommand extends ContainerAwareCommand
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$imageLoaderService = $this->getContainer()->get('service.loader.image'); $this->imageLoader->setOutput($output);
$imageLoaderService->setOutput($output);
$color = $input->getOption('color'); $color = $input->getOption('color');
if ($color !== null && $input->getOption('rebrickable')) { if ($color !== null && $input->getOption('rebrickable')) {
$imageLoaderService->loadColorFromRebrickable($color); $this->imageLoader->loadColorFromRebrickable($color);
} }
if ($input->getOption('missing')) { if ($input->getOption('missing')) {
$imageLoaderService->loadMissingModelImages(); $this->imageLoader->loadMissingModelImages();
} }
} }
} }

View File

@ -14,6 +14,22 @@ class LoadLdrawCommand extends ContainerAwareCommand
{ {
use LockableTrait; use LockableTrait;
/** @var ModelLoader */
private $modelLoader;
/**
* LoadLdrawCommand constructor.
*
* @param string $name
* @param ModelLoader $modelLoader
*/
public function __construct($name = null, ModelLoader $modelLoader)
{
$this->modelLoader = $modelLoader;
parent::__construct($name);
}
protected function configure() protected function configure()
{ {
$this $this
@ -38,10 +54,8 @@ class LoadLdrawCommand extends ContainerAwareCommand
return 1; return 1;
} }
/** @var ModelLoader $modelLoader */ $this->modelLoader->setOutput($output);
$modelLoader = $this->getContainer()->get('service.loader.model'); $this->modelLoader->setRewrite($input->getOption('update'));
$modelLoader->setOutput($output);
$modelLoader->setRewrite($input->getOption('update'));
if (!$input->getOption('file') && !$input->getOption('all')) { if (!$input->getOption('file') && !$input->getOption('all')) {
$output->writeln('Either the --all or --file option is required'); $output->writeln('Either the --all or --file option is required');
@ -50,10 +64,10 @@ class LoadLdrawCommand extends ContainerAwareCommand
} }
if ($ldraw = $input->getOption('ldraw')) { if ($ldraw = $input->getOption('ldraw')) {
$modelLoader->setLDrawLibraryContext(realpath($ldraw)); $this->modelLoader->setLDrawLibraryContext(realpath($ldraw));
} else { } else {
$ldraw = $modelLoader->downloadLibrary($this->getContainer()->getParameter('app.ld_library_download_url')); $ldraw = $this->modelLoader->downloadLibrary($this->getContainer()->getParameter('app.ld_library_download_url'));
$modelLoader->setLDrawLibraryContext($ldraw); $this->modelLoader->setLDrawLibraryContext($ldraw);
} }
if (($path = $input->getOption('file')) != null) { if (($path = $input->getOption('file')) != null) {
@ -62,7 +76,7 @@ class LoadLdrawCommand extends ContainerAwareCommand
"Loading model: {$path}", "Loading model: {$path}",
]); ]);
$modelLoader->loadOne($file); $this->modelLoader->loadOne($file);
$errorCount = $this->getContainer()->get('monolog.logger.loader')->countErrors(); $errorCount = $this->getContainer()->get('monolog.logger.loader')->countErrors();
$errors = $errorCount ? '<error>'.$errorCount.'</error>' : '<info>0</info>'; $errors = $errorCount ? '<error>'.$errorCount.'</error>' : '<info>0</info>';
@ -75,7 +89,7 @@ class LoadLdrawCommand extends ContainerAwareCommand
// Load all models inside ldraw/parts directory // Load all models inside ldraw/parts directory
if ($input->getOption('all')) { if ($input->getOption('all')) {
$modelLoader->loadAll(); $this->modelLoader->loadAll();
$errorCount = $this->getContainer()->get('monolog.logger.loader')->countErrors(); $errorCount = $this->getContainer()->get('monolog.logger.loader')->countErrors();
$errors = $errorCount ? '<error>'.$errorCount.'</error>' : '<info>0</info>'; $errors = $errorCount ? '<error>'.$errorCount.'</error>' : '<info>0</info>';

View File

@ -2,6 +2,7 @@
namespace AppBundle\Command; namespace AppBundle\Command;
use AppBundle\Service\Loader\RebrickableLoader;
use League\Flysystem\Exception; use League\Flysystem\Exception;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\ArrayInput;
@ -10,6 +11,22 @@ use Symfony\Component\Console\Output\OutputInterface;
class LoadRebrickableDataCommand extends ContainerAwareCommand class LoadRebrickableDataCommand extends ContainerAwareCommand
{ {
/** @var RebrickableLoader */
private $rebrickableLoader;
/**
* LoadRebrickableDataCommand constructor.
*
* @param string $name
* @param RebrickableLoader $rebrickableLoader
*/
public function __construct($name = null, RebrickableLoader $rebrickableLoader)
{
$this->rebrickableLoader = $rebrickableLoader;
parent::__construct($name);
}
protected function configure() protected function configure()
{ {
$this $this
@ -20,11 +37,11 @@ class LoadRebrickableDataCommand extends ContainerAwareCommand
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$rebrickableLoader = $this->getContainer()->get('service.loader.rebrickable'); $this->rebrickableLoader = $this->getContainer()->get('service.loader.rebrickable');
$rebrickableLoader->setOutput($output); $this->rebrickableLoader->setOutput($output);
try { try {
$rebrickableLoader->loadAll(); $this->rebrickableLoader->loadAll();
} catch (Exception $exception) { } catch (Exception $exception) {
$output->writeln("<error>{$exception->getMessage()}</error>"); $output->writeln("<error>{$exception->getMessage()}</error>");

View File

@ -11,6 +11,22 @@ use Symfony\Component\Console\Output\OutputInterface;
class LoadRelationCommand extends ContainerAwareCommand class LoadRelationCommand extends ContainerAwareCommand
{ {
/** @var RelationLoader */
private $relationLoader;
/**
* LoadRelationCommand constructor.
*
* @param $name
* @param RelationLoader $relationLoader
*/
public function __construct($name = null, RelationLoader $relationLoader)
{
$this->relationLoader = $relationLoader;
parent::__construct($name);
}
protected function configure() protected function configure()
{ {
$this $this
@ -26,9 +42,7 @@ class LoadRelationCommand extends ContainerAwareCommand
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
/** @var RelationLoader $relationLoader */ $this->relationLoader->setOutput($output);
$relationLoader = $this->getContainer()->get('service.loader.relation');
$relationLoader->setOutput($output);
$output->writeln([ $output->writeln([
'<fg=cyan>------------------------------------------------------------------------------</>', '<fg=cyan>------------------------------------------------------------------------------</>',
@ -37,9 +51,9 @@ class LoadRelationCommand extends ContainerAwareCommand
]); ]);
if ($input->getOption('rewrite')) { if ($input->getOption('rewrite')) {
$relationLoader->loadAll(); $this->relationLoader->loadAll();
} else { } else {
$relationLoader->loadNotPaired(); $this->relationLoader->loadNotPaired();
} }
$output->writeln(['<info>Done!</info>']); $output->writeln(['<info>Done!</info>']);

View File

@ -2,13 +2,12 @@
namespace AppBundle\Controller; namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class AjaxController extends Controller class AjaxController extends AbstractController
{ {
/** /**
* @Route("/set_tab/{tab}", name="set_tab", requirements={"tab"=".+"}) * @Route("/set_tab/{tab}", name="set_tab", requirements={"tab"=".+"})
@ -19,7 +18,7 @@ class AjaxController extends Controller
$session->set('tab', $tab); $session->set('tab', $tab);
$response = new Response(); $response = new Response();
return $response;
return $response;
} }
} }

View File

@ -19,11 +19,11 @@ class SetController extends Controller
* @Route("/{id}/instructions", name="brickset_instructions") * @Route("/{id}/instructions", name="brickset_instructions")
* @Method("GET") * @Method("GET")
*/ */
public function instructionsAction(Request $request, $id) public function instructionsAction(Request $request, $id, BricksetManager $bricksetManager)
{ {
$instructions = []; $instructions = [];
try { try {
$instructions = $this->get('api.manager.brickset')->getSetInstructions($id); $instructions = $bricksetManager->getSetInstructions($id);
} catch (ApiException $e) { } catch (ApiException $e) {
$this->addFlash('error', $e->getService()); $this->addFlash('error', $e->getService());
} catch (\Exception $e) { } catch (\Exception $e) {
@ -49,13 +49,11 @@ class SetController extends Controller
* @Route("/{id}/reviews", name="brickset_reviews") * @Route("/{id}/reviews", name="brickset_reviews")
* @Method("GET") * @Method("GET")
*/ */
public function reviewsAction(Request $request, $id) public function reviewsAction(Request $request, $id, BricksetManager $bricksetManager)
{ {
$reviews = []; $reviews = [];
$number = null; $number = null;
try { try {
/** @var BricksetManager $bricksetManager */
$bricksetManager = $this->get('api.manager.brickset');
$reviews = $bricksetManager->getSetReviews($id); $reviews = $bricksetManager->getSetReviews($id);
$number = $bricksetManager->getSetById($id)->getLegoSetID(); $number = $bricksetManager->getSetById($id)->getLegoSetID();
} catch (ApiException $e) { } catch (ApiException $e) {
@ -84,11 +82,11 @@ class SetController extends Controller
* @Route("/{id}/images", name="brickset_images") * @Route("/{id}/images", name="brickset_images")
* @Method("GET") * @Method("GET")
*/ */
public function imagesAction(Request $request, $id) public function imagesAction(Request $request, $id, BricksetManager $bricksetManager)
{ {
$images = []; $images = [];
try { try {
$images = $this->get('api.manager.brickset')->getAdditionalImages($id); $images = $bricksetManager->getAdditionalImages($id);
} catch (ApiException $e) { } catch (ApiException $e) {
$this->addFlash('error', $e->getService()); $this->addFlash('error', $e->getService());
} catch (\Exception $e) { } catch (\Exception $e) {
@ -114,11 +112,11 @@ class SetController extends Controller
* @Route("/{id}/description", name="brickset_description") * @Route("/{id}/description", name="brickset_description")
* @Method("GET") * @Method("GET")
*/ */
public function descriptionAction(Request $request, $id) public function descriptionAction(Request $request, $id, BricksetManager $bricksetManager)
{ {
$desription = null; $desription = null;
try { try {
$desription = $this->get('api.manager.brickset')->getSetById($id)->getDescription(); $desription = $bricksetManager->getSetById($id)->getDescription();
} catch (ApiException $e) { } catch (ApiException $e) {
$this->addFlash('error', $e->getService()); $this->addFlash('error', $e->getService());
} catch (\Exception $e) { } catch (\Exception $e) {

View File

@ -2,7 +2,10 @@
namespace AppBundle\Controller; namespace AppBundle\Controller;
use AppBundle\Entity\Color;
use AppBundle\Service\ColorService;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller;
/** /**
@ -10,17 +13,15 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller;
* *
* @Route("colors") * @Route("colors")
*/ */
class ColorController extends Controller class ColorController extends AbstractController
{ {
/** /**
* @Route("/", name="color_index") * @Route("/", name="color_index")
*/ */
public function indexAction() public function indexAction(ColorService $colorService)
{ {
$colors = $this->get('repository.color')->findAll();
return $this->render('color/index.html.twig', [ return $this->render('color/index.html.twig', [
'colors' => $colors, 'colors' => $colorService->getAll(),
]); ]);
} }
} }

View File

@ -2,28 +2,21 @@
namespace AppBundle\Controller; namespace AppBundle\Controller;
use AppBundle\Repository\LDraw\ModelRepository; use AppBundle\Service\ModelService;
use AppBundle\Repository\Rebrickable\SetRepository; use AppBundle\Service\SetService;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends Controller class DefaultController extends AbstractController
{ {
/** /**
* @Route("/", name="homepage") * @Route("/", name="homepage")
*/ */
public function indexAction(Request $request) public function indexAction(SetService $setService, ModelService $modelService)
{ {
/** @var ModelRepository $modelRepository */
$modelRepository = $this->get('repository.ldraw.model');
/** @var SetRepository $setRepository */
$setRepository = $this->get('repository.rebrickable.set');
return $this->render('default/index.html.twig', [ return $this->render('default/index.html.twig', [
'models' => $modelRepository->count(), 'models' => $modelService->getTotalCount(),
'sets' => $setRepository->count(), 'sets' => $setService->getTotalCount(),
]); ]);
} }
} }

View File

@ -2,6 +2,7 @@
namespace AppBundle\Controller; namespace AppBundle\Controller;
use League\Flysystem\Filesystem;
use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
@ -19,10 +20,8 @@ class MediaController extends Controller
* *
* @return Response * @return Response
*/ */
public function fileAction($path) public function fileAction($path, Filesystem $mediaFilesystem)
{ {
$mediaFilesystem = $this->get('oneup_flysystem.media_filesystem');
if ($mediaFilesystem->has($path)) { if ($mediaFilesystem->has($path)) {
$response = new BinaryFileResponse($mediaFilesystem->getAdapter()->getPathPrefix().DIRECTORY_SEPARATOR.$path); $response = new BinaryFileResponse($mediaFilesystem->getAdapter()->getPathPrefix().DIRECTORY_SEPARATOR.$path);
$response->headers->set('Content-Type', $mediaFilesystem->getMimetype($path)); $response->headers->set('Content-Type', $mediaFilesystem->getMimetype($path));

View File

@ -5,12 +5,14 @@ namespace AppBundle\Controller;
use AppBundle\Entity\LDraw\Model; use AppBundle\Entity\LDraw\Model;
use AppBundle\Form\Search\ModelSearchType; use AppBundle\Form\Search\ModelSearchType;
use AppBundle\Model\ModelSearch; use AppBundle\Model\ModelSearch;
use AppBundle\Repository\Rebrickable\SetRepository; use AppBundle\Service\ModelService;
use AppBundle\Service\SetService;
use AppBundle\Service\ZipService;
use Knp\Component\Pager\Paginator; use Knp\Component\Pager\Paginator;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
@ -28,11 +30,11 @@ class ModelController extends Controller
* *
* @Route("/", name="model_index") * @Route("/", name="model_index")
*/ */
public function indexAction(Request $request) public function indexAction(Request $request, FormFactoryInterface $formFactory)
{ {
$modelSearch = new ModelSearch(); $modelSearch = new ModelSearch();
$form = $this->get('form.factory')->createNamedBuilder('', ModelSearchType::class, $modelSearch)->getForm(); $form = $formFactory->createNamedBuilder('', ModelSearchType::class, $modelSearch)->getForm();
$form->handleRequest($request); $form->handleRequest($request);
$elasticaManager = $this->get('fos_elastica.manager'); $elasticaManager = $this->get('fos_elastica.manager');
@ -58,21 +60,14 @@ class ModelController extends Controller
* @Route("/{id}", name="model_detail") * @Route("/{id}", name="model_detail")
* @Method("GET") * @Method("GET")
*/ */
public function detailAction($id) public function detailAction($id, ModelService $modelService)
{ {
/** @var Model $model */ if ($model = $modelService->findModel($id)) {
if ($model = $this->get('repository.ldraw.model')->findOneByNumber($id)) {
try { try {
$subparts = $this->get('service.model')->getAllSubparts($model);
$sets = $model != null ? $this->get('repository.rebrickable.set')->findAllByModel($model) : null;
$related = $this->get('repository.ldraw.model')->findAllRelatedModels($model->getId());
return $this->render('model/detail.html.twig', [ return $this->render('model/detail.html.twig', [
'model' => $model, 'model' => $model,
'sets' => $sets, 'siblings' => $modelService->getSiblings($model),
'related' => $related, 'submodels' => $modelService->getSubmodels($model),
'subparts' => $subparts,
]); ]);
} catch (\Exception $e) { } catch (\Exception $e) {
$this->addFlash('error', $e->getMessage()); $this->addFlash('error', $e->getMessage());
@ -82,21 +77,49 @@ class ModelController extends Controller
return $this->render('error/error.html.twig'); return $this->render('error/error.html.twig');
} }
/**
* @Route("/{id}/sets", name="model_sets")
* @Method("GET")
*/
public function setsAction(Request $request, Model $model, SetService $setService)
{
/** @var Paginator $paginator */
$paginator = $this->get('knp_paginator');
$sets = $paginator->paginate(
$setService->getAllByModel($model),
$request->query->getInt('page', 1)/*page number*/,
$request->query->getInt('limit', 16)/*limit per page*/
);
$template = $this->render('model/tabs/sets.html.twig', [
'sets' => $sets,
]);
if ($request->isXmlHttpRequest()) {
$json = json_encode($template->getContent());
$response = new Response($json, 200);
$response->headers->set('Content-Type', 'application/json');
return $response;
}
return $template;
}
/** /**
* @Route("/{id}/zip", name="model_zip") * @Route("/{id}/zip", name="model_zip")
* @Method("GET") * @Method("GET")
*/ */
public function zipAction(Request $request, Model $model) public function zipAction(Model $model, ZipService $zipService)
{ {
// escape forbidden characters from filename // escape forbidden characters from filename
$filename = preg_replace('/[^a-z0-9()\-\.]/i', '_', "{$model->getId()}_{$model->getName()}"); $filename = preg_replace('/[^a-z0-9()\-\.]/i', '_', "{$model->getId()}_{$model->getName()}");
$zip = $this->get('service.zip')->createFromModel($model, $filename, true); $zip = $zipService->createFromModel($model, $filename, true);
$response = new BinaryFileResponse($zip); $response = new BinaryFileResponse($zip);
$response->headers->set('Content-Type', 'application/zip'); $response->headers->set('Content-Type', 'application/zip');
// Create the disposition of the file // Create the disposition of the file
$disposition = $response->headers->makeDisposition( $disposition = $response->headers->makeDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT, ResponseHeaderBag::DISPOSITION_ATTACHMENT,

View File

@ -3,9 +3,14 @@
namespace AppBundle\Controller; namespace AppBundle\Controller;
use AppBundle\Api\Exception\EmptyResponseException; use AppBundle\Api\Exception\EmptyResponseException;
use AppBundle\Api\Manager\RebrickableManager;
use AppBundle\Entity\Rebrickable\Part; use AppBundle\Entity\Rebrickable\Part;
use AppBundle\Service\SetService;
use Knp\Component\Pager\Paginator;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/** /**
* Part controller. * Part controller.
@ -19,7 +24,7 @@ class PartController extends Controller
* *
* @Route("/{id}", name="part_detail") * @Route("/{id}", name="part_detail")
*/ */
public function detailAction(Part $part) public function detailAction(Part $part, RebrickableManager $rebrickableManager)
{ {
$apiPart = null; $apiPart = null;
if ($part) { if ($part) {
@ -28,7 +33,7 @@ class PartController extends Controller
} }
try { try {
$apiPart = $this->get('api.manager.rebrickable')->getPart($part->getId()); $apiPart = $rebrickableManager->getPart($part->getId());
} catch (EmptyResponseException $e) { } catch (EmptyResponseException $e) {
$this->addFlash('warning', 'Part not found'); $this->addFlash('warning', 'Part not found');
} catch (\Exception $e) { } catch (\Exception $e) {
@ -43,4 +48,32 @@ class PartController extends Controller
return $this->render('error/error.html.twig'); return $this->render('error/error.html.twig');
} }
/**
* @Route("/{id}/sets", name="part_sets")
*/
public function setsAction(Request $request, Part $part, SetService $setService)
{
/** @var Paginator $paginator */
$paginator = $this->get('knp_paginator');
$sets = $paginator->paginate(
$setService->getAllByPart($part),
$request->query->getInt('page', 1)/*page number*/,
$request->query->getInt('limit', 16)/*limit per page*/
);
$template = $this->render('model/tabs/sets.html.twig', [
'sets' => $sets,
]);
if ($request->isXmlHttpRequest()) {
$json = json_encode($template->getContent());
$response = new Response($json, 200);
$response->headers->set('Content-Type', 'application/json');
return $response;
}
return $template;
}
} }

View File

@ -3,15 +3,16 @@
namespace AppBundle\Controller; namespace AppBundle\Controller;
use AppBundle\Api\Exception\ApiException; use AppBundle\Api\Exception\ApiException;
use AppBundle\Entity\Rebrickable\Inventory_Set; use AppBundle\Api\Manager\BricksetManager;
use AppBundle\Entity\Rebrickable\Set; use AppBundle\Entity\Rebrickable\Set;
use AppBundle\Form\Search\SetSearchType; use AppBundle\Form\Search\SetSearchType;
use AppBundle\Model\SetSearch; use AppBundle\Model\SetSearch;
use AppBundle\Repository\Rebrickable\Inventory_PartRepository;
use AppBundle\Repository\Search\SetRepository; use AppBundle\Repository\Search\SetRepository;
use AppBundle\Service\SetService; use AppBundle\Service\SetService;
use AppBundle\Service\ZipService;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
@ -24,12 +25,16 @@ class SetController extends Controller
{ {
/** /**
* @Route("/", name="set_index") * @Route("/", name="set_index")
*
* @param Request $request
*
* @return Response
*/ */
public function indexAction(Request $request) public function indexAction(Request $request, FormFactoryInterface $formFactory)
{ {
$setSearch = new SetSearch(); $setSearch = new SetSearch();
$form = $this->get('form.factory')->createNamedBuilder('', SetSearchType::class, $setSearch)->getForm(); $form = $formFactory->createNamedBuilder('', SetSearchType::class, $setSearch)->getForm();
$form->handleRequest($request); $form->handleRequest($request);
/** @var SetRepository $setRepository */ /** @var SetRepository $setRepository */
@ -51,19 +56,17 @@ class SetController extends Controller
/** /**
* @Route("/{id}", name="set_detail") * @Route("/{id}", name="set_detail")
*
* @param Set $set
*
* @return Response
*/ */
public function detailAction(Request $request, Set $set) public function detailAction(Set $set, SetService $setService, BricksetManager $bricksetManager)
{ {
/** @var Inventory_PartRepository $inventoryPartRepository */
$inventoryPartRepository = $this->get('repository.rebrickable.inventoryPart');
/** @var SetService $setService */
$setService = $this->get('service.set');
$bricksetSet = null; $bricksetSet = null;
$partCount = $inventoryPartRepository->getPartCount($set, false);
try { try {
if (!($bricksetSet = $this->get('api.manager.brickset')->getSetByNumber($set->getId()))) { if (!($bricksetSet = $bricksetManager->getSetByNumber($set->getId()))) {
$this->addFlash('warning', "{$set->getId()} not found in Brickset database"); $this->addFlash('warning', "{$set->getId()} not found in Brickset database");
} }
} catch (ApiException $e) { } catch (ApiException $e) {
@ -75,33 +78,22 @@ class SetController extends Controller
return $this->render('set/detail.html.twig', [ return $this->render('set/detail.html.twig', [
'set' => $set, 'set' => $set,
'brset' => $bricksetSet, 'brset' => $bricksetSet,
'partCount' => $partCount, 'partCount' => $setService->getPartCount($set),
]); ]);
} }
/** /**
* @Route("/{id}/inventory", name="set_inventory") * @Route("/{id}/inventory", name="set_inventory")
*/ */
public function inventoryAction(Request $request, Set $set) public function inventoryAction(Request $request, Set $set, SetService $setService)
{ {
$em = $this->getDoctrine()->getManager();
$inventorySets = $em->getRepository(Inventory_Set::class)->findAllBySetNumber($set->getId());
$setService = $this->get('service.set');
$inventoryPartRepository = $this->get('repository.rebrickable.inventoryPart');
$models = $setService->getModels($set, false);
$missing = $setService->getParts($set, false, false);
$missingCount = $inventoryPartRepository->getPartCount($set, false, false);
$partCount = $inventoryPartRepository->getPartCount($set, false);
$template = $this->render('set/tabs/inventory.html.twig', [ $template = $this->render('set/tabs/inventory.html.twig', [
'inventorySets' => $inventorySets, 'inventorySets' => $setService->getAllSubSets($set),
'set' => $set, 'set' => $set,
'missing' => $missing, 'missing' => $setService->getParts($set, false, false),
'models' => $models, 'models' => $setService->getModels($set, false),
'missingCount' => $missingCount, 'missingCount' => $setService->getPartCount($set, false, false),
'partCount' => $partCount, 'partCount' => $setService->getPartCount($set, false),
]); ]);
if ($request->isXmlHttpRequest()) { if ($request->isXmlHttpRequest()) {
@ -118,10 +110,8 @@ class SetController extends Controller
/** /**
* @Route("/{id}/models", name="set_models") * @Route("/{id}/models", name="set_models")
*/ */
public function modelsAction(Request $request, Set $set) public function modelsAction(Request $request, Set $set, SetService $setService)
{ {
$setService = $this->get('service.set');
$models = null; $models = null;
$missing = null; $missing = null;
@ -152,11 +142,8 @@ class SetController extends Controller
/** /**
* @Route("/{id}/colors", name="set_colors") * @Route("/{id}/colors", name="set_colors")
*/ */
public function colorsAction(Request $request, Set $set) public function colorsAction(Request $request, Set $set, SetService $setService)
{ {
/** @var SetService $setService */
$setService = $this->get('service.set');
$colors = null; $colors = null;
$missing = null; $missing = null;
@ -187,14 +174,14 @@ class SetController extends Controller
/** /**
* @Route("/{id}/zip", name="set_zip") * @Route("/{id}/zip", name="set_zip")
*/ */
public function zipAction(Request $request, Set $set) public function zipAction(Request $request, Set $set, ZipService $zipService)
{ {
$sorted = $request->query->get('sorted') == 1 ? true : false; $sorted = $request->query->get('sorted') == 1 ? true : false;
$sort = $sorted ? 'Multi-Color' : 'Uni-Color'; $sort = $sorted ? 'Multi-Color' : 'Uni-Color';
// escape forbidden characters from filename // escape forbidden characters from filename
$filename = preg_replace('/[^a-z0-9()\-\.]/i', '_', "{$set->getId()}_{$set->getName()}({$sort})"); $filename = preg_replace('/[^a-z0-9()\-\.]/i', '_', "{$set->getId()}_{$set->getName()}({$sort})");
$zip = $this->get('service.zip')->createFromSet($set, $filename, $sorted); $zip = $zipService->createFromSet($set, $filename, $sorted);
$response = new BinaryFileResponse($zip); $response = new BinaryFileResponse($zip);
$response->headers->set('Content-Type', 'application/zip'); $response->headers->set('Content-Type', 'application/zip');

View File

@ -1,6 +1,6 @@
<?php <?php
namespace AppBundle\Exception; namespace AppBundle\Exception\Loader;
use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Exception\LogicException;
use Throwable; use Throwable;

View File

@ -5,6 +5,7 @@ namespace AppBundle\Form\Search;
use AppBundle\Entity\LDraw\Category; use AppBundle\Entity\LDraw\Category;
use AppBundle\Model\ModelSearch; use AppBundle\Model\ModelSearch;
use AppBundle\Repository\LDraw\CategoryRepository; use AppBundle\Repository\LDraw\CategoryRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;
@ -16,9 +17,14 @@ class ModelSearchType extends AbstractType
/** @var CategoryRepository */ /** @var CategoryRepository */
private $categoryRepository; private $categoryRepository;
public function __construct(CategoryRepository $categoryRepository) /**
* ModelSearchType constructor.
*
* @param EntityManagerInterface $em
*/
public function __construct(EntityManagerInterface $em)
{ {
$this->categoryRepository = $categoryRepository; $this->categoryRepository = $em->getRepository(Category::class);
} }
public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)

View File

@ -2,11 +2,13 @@
namespace AppBundle\Form\Search; namespace AppBundle\Form\Search;
use AppBundle\Entity\Rebrickable\Set;
use AppBundle\Entity\Rebrickable\Theme; use AppBundle\Entity\Rebrickable\Theme;
use AppBundle\Form\NumberRangeType; use AppBundle\Form\NumberRangeType;
use AppBundle\Model\SetSearch; use AppBundle\Model\SetSearch;
use AppBundle\Repository\Rebrickable\SetRepository; use AppBundle\Repository\Rebrickable\SetRepository;
use AppBundle\Repository\Rebrickable\ThemeRepository; use AppBundle\Repository\Rebrickable\ThemeRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;
@ -21,10 +23,15 @@ class SetSearchType extends AbstractType
/** @var SetRepository */ /** @var SetRepository */
private $setRepository; private $setRepository;
public function __construct(ThemeRepository $themeRepository, SetRepository $setRepository) /**
* SetSearchType constructor.
*
* @param EntityManagerInterface $em
*/
public function __construct(EntityManagerInterface $em)
{ {
$this->themeRepository = $themeRepository; $this->themeRepository = $em->getRepository(Theme::class);
$this->setRepository = $setRepository; $this->setRepository = $em->getRepository(Set::class);
} }
public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)

View File

@ -9,6 +9,8 @@ abstract class BaseImageLoader implements LoaderInterface
abstract public function find($path); abstract public function find($path);
/** /**
* Check if file on remote url exists.
*
* @param string $url * @param string $url
* *
* @return bool * @return bool

View File

@ -4,6 +4,7 @@ namespace AppBundle\Imagine;
use AppBundle\Api\Manager\RebrickableManager; use AppBundle\Api\Manager\RebrickableManager;
use League\Flysystem\Filesystem; use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemInterface;
use Liip\ImagineBundle\Exception\Binary\Loader\NotLoadableException; use Liip\ImagineBundle\Exception\Binary\Loader\NotLoadableException;
class PartImageLoader extends BaseImageLoader class PartImageLoader extends BaseImageLoader
@ -19,10 +20,10 @@ class PartImageLoader extends BaseImageLoader
/** /**
* PartImageLoader constructor. * PartImageLoader constructor.
* *
* @param $rebrickableManager * @param RebrickableManager $rebrickableManager
* @param $mediaFilesystem * @param FilesystemInterface $mediaFilesystem
*/ */
public function __construct($rebrickableManager, $mediaFilesystem) public function __construct(RebrickableManager $rebrickableManager, FilesystemInterface $mediaFilesystem)
{ {
$this->mediaFilesystem = $mediaFilesystem; $this->mediaFilesystem = $mediaFilesystem;
$this->rebrickableManager = $rebrickableManager; $this->rebrickableManager = $rebrickableManager;

View File

@ -4,6 +4,7 @@ namespace AppBundle\Imagine;
use AppBundle\Api\Manager\BricksetManager; use AppBundle\Api\Manager\BricksetManager;
use League\Flysystem\Filesystem; use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemInterface;
use Liip\ImagineBundle\Exception\Binary\Loader\NotLoadableException; use Liip\ImagineBundle\Exception\Binary\Loader\NotLoadableException;
class SetImageLoader extends BaseImageLoader class SetImageLoader extends BaseImageLoader
@ -19,9 +20,10 @@ class SetImageLoader extends BaseImageLoader
/** /**
* SetImageLoader constructor. * SetImageLoader constructor.
* *
* @param $bricksetManager * @param BricksetManager $bricksetManager
* @param FilesystemInterface $mediaFilesystem
*/ */
public function __construct($bricksetManager, $mediaFilesystem) public function __construct(BricksetManager $bricksetManager, FilesystemInterface $mediaFilesystem)
{ {
$this->bricksetManager = $bricksetManager; $this->bricksetManager = $bricksetManager;
$this->mediaFilesystem = $mediaFilesystem; $this->mediaFilesystem = $mediaFilesystem;

View File

@ -89,7 +89,7 @@ class ModelRepository extends BaseRepository
return $queryBuilder->getQuery()->getResult(); return $queryBuilder->getQuery()->getResult();
} }
public function findAllRelatedModels($number) public function findAllRelatedModels(Model $model)
{ {
$queryBuilder = $this->createQueryBuilder('model'); $queryBuilder = $this->createQueryBuilder('model');
@ -99,7 +99,7 @@ class ModelRepository extends BaseRepository
->join(Subpart::class, 'parent', JOIN::WITH, 'subpart.parent = parent.parent') ->join(Subpart::class, 'parent', JOIN::WITH, 'subpart.parent = parent.parent')
->join(Model::class, 'related', JOIN::WITH, 'related.id = parent.subpart') ->join(Model::class, 'related', JOIN::WITH, 'related.id = parent.subpart')
->where('model.id = :number') ->where('model.id = :number')
->setParameter('number', $number) ->setParameter('number', $model->getId())
->andWhere('related.id != :number') ->andWhere('related.id != :number')
->distinct(true); ->distinct(true);

View File

@ -48,6 +48,14 @@ class Inventory_PartRepository extends BaseRepository
return $queryBuilder->getQuery()->getResult(); return $queryBuilder->getQuery()->getResult();
} }
/**
* Find all Inventory_Parts with $color in set.
*
* @param string $number
* @param int $color
*
* @return array
*/
public function findAllBySetNumberAndColor($number, $color) public function findAllBySetNumberAndColor($number, $color)
{ {
$inventory = $this->getEntityManager()->getRepository(Inventory::class)->findNewestInventoryBySetNumber($number); $inventory = $this->getEntityManager()->getRepository(Inventory::class)->findNewestInventoryBySetNumber($number);
@ -61,6 +69,15 @@ class Inventory_PartRepository extends BaseRepository
return $queryBuilder->getQuery()->getResult(); return $queryBuilder->getQuery()->getResult();
} }
/**
* Get total part count of Set.
*
* @param Set $set
* @param bool $spare If true - find all spare parts, false - find all regular parts, null - spare and regular parts
* @param bool $model If true - find all parts with model relation, false - find all parts without model relation, null - all parts
*
* @return mixed
*/
public function getPartCount(Set $set, $spare = null, $model = null) public function getPartCount(Set $set, $spare = null, $model = null)
{ {
$inventory = $this->getEntityManager()->getRepository(Inventory::class)->findNewestInventoryBySetNumber($set->getId()); $inventory = $this->getEntityManager()->getRepository(Inventory::class)->findNewestInventoryBySetNumber($set->getId());

View File

@ -23,14 +23,14 @@ class SetRepository extends BaseRepository
return $queryBuilder->getQuery()->getResult(); return $queryBuilder->getQuery()->getResult();
} }
public function findAllByPartNumber($number) public function findAllByPart(Part $part)
{ {
$queryBuilder = $this->createQueryBuilder('s') $queryBuilder = $this->createQueryBuilder('s')
->join(Inventory::class, 'inventory', JOIN::WITH, 'inventory.set = s.id') ->join(Inventory::class, 'inventory', JOIN::WITH, 'inventory.set = s.id')
->join(Inventory_Part::class, 'inventory_part', JOIN::WITH, 'inventory.id = inventory_part.inventory') ->join(Inventory_Part::class, 'inventory_part', JOIN::WITH, 'inventory.id = inventory_part.inventory')
->join(Part::class, 'part', Join::WITH, 'inventory_part.part = part.id') ->join(Part::class, 'part', Join::WITH, 'inventory_part.part = part.id')
->where('part.id LIKE :number') ->where('part.id LIKE :number')
->setParameter('number', $number) ->setParameter('number', $part->getId())
->distinct(true); ->distinct(true);
return $queryBuilder->getQuery()->getResult(); return $queryBuilder->getQuery()->getResult();

View File

@ -4,14 +4,12 @@ namespace AppBundle\Repository\Rebrickable;
use AppBundle\Entity\Rebrickable\Theme; use AppBundle\Entity\Rebrickable\Theme;
use AppBundle\Repository\BaseRepository; use AppBundle\Repository\BaseRepository;
use Doctrine\ORM\Query\Expr\Join;
class ThemeRepository extends BaseRepository class ThemeRepository extends BaseRepository
{ {
public function findAllSubthemes(Theme $theme) public function findAllSubthemes(Theme $theme)
{ {
$queryBuilder = $this->createQueryBuilder('theme') $queryBuilder = $this->createQueryBuilder('theme')
// ->leftJoin(Theme::class, 'theme', Join::WITH, 'subtheme.parent = theme.id')
->where('theme.parent = :id') ->where('theme.parent = :id')
->setParameter('id', $theme->getId()); ->setParameter('id', $theme->getId());

View File

@ -9,7 +9,7 @@ use FOS\ElasticaBundle\Repository;
class ModelRepository extends Repository class ModelRepository extends Repository
{ {
/** /**
* Create search query from ModelSearch entity * Create search query from ModelSearch entity.
* *
* @param ModelSearch $modelSearch * @param ModelSearch $modelSearch
* *
@ -50,10 +50,11 @@ class ModelRepository extends Repository
} }
/** /**
* Find models by query with highlighted matched values * Find models by query with highlighted matched values.
* *
* @param string $query * @param string $query
* @param int $limit * @param int $limit
*
* @return mixed * @return mixed
*/ */
public function findHighlighted($query, $limit = 500) public function findHighlighted($query, $limit = 500)

View File

@ -10,13 +10,12 @@ use Elastica\Query\Range;
use FOS\ElasticaBundle\Repository; use FOS\ElasticaBundle\Repository;
/** /**
* Class SetRepository * Class SetRepository.
* @package AppBundle\Repository\Search
*/ */
class SetRepository extends Repository class SetRepository extends Repository
{ {
/** /**
* Create search query from SetSearch entity * Create search query from SetSearch entity.
* *
* @param SetSearch $setSearch * @param SetSearch $setSearch
* *
@ -70,7 +69,8 @@ class SetRepository extends Repository
/** /**
* @param SetSearch $setSearch * @param SetSearch $setSearch
* @param int $limit * @param int $limit
*
* @return array * @return array
*/ */
public function search(SetSearch $setSearch, $limit = 500) public function search(SetSearch $setSearch, $limit = 500)
@ -80,12 +80,12 @@ class SetRepository extends Repository
return $this->find($query, $limit); return $this->find($query, $limit);
} }
/** /**
* Find sets by query with highlighted matched values * Find sets by query with highlighted matched values.
* *
* @param string $query * @param string $query
* @param int $limit * @param int $limit
*
* @return mixed * @return mixed
*/ */
public function findHighlighted($query, $limit = 500) public function findHighlighted($query, $limit = 500)

View File

@ -0,0 +1,26 @@
<?php
namespace AppBundle\Service;
use AppBundle\Entity\Color;
use AppBundle\Repository\ColorRepository;
use Doctrine\ORM\EntityManagerInterface;
class ColorService
{
/** @var ColorRepository */
private $colorRepository;
/**
* ColorService constructor.
*/
public function __construct(EntityManagerInterface $em)
{
$this->colorRepository = $em->getRepository(Color::class);
}
public function getAll()
{
return $this->colorRepository->findAll();
}
}

View File

@ -6,8 +6,9 @@ use AppBundle\Exception\FileNotFoundException;
use AppBundle\Exception\WriteErrorException; use AppBundle\Exception\WriteErrorException;
use AppBundle\Transformer\FormatTransformer; use AppBundle\Transformer\FormatTransformer;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Monolog\Logger; use Monolog\Logger;
use Symfony\Bundle\FrameworkBundle\Translation\Translator; use Psr\Log\LoggerInterface;
use Symfony\Component\Asset\Exception\LogicException; use Symfony\Component\Asset\Exception\LogicException;
use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@ -41,19 +42,16 @@ abstract class BaseLoader
private $formatTransformer; private $formatTransformer;
/** /**
* Loader constructor. * BaseLoader constructor.
* *
* @param EntityManager $em * @param EntityManagerInterface $em
* @param Logger $logger * @param LoggerInterface $logger
* @param Translator $formatTransformer
*/ */
public function setArguments(EntityManager $em, $logger, $formatTransformer) public function __construct(EntityManagerInterface $em, LoggerInterface $logger)
{ {
$this->em = $em; $this->em = $em;
$this->em->getConnection()->getConfiguration()->setSQLLogger(null);
$this->logger = $logger; $this->logger = $logger;
$this->formatTransformer = $formatTransformer; $this->formatTransformer = new FormatTransformer();
} }
public function setOutput(OutputInterface $output) public function setOutput(OutputInterface $output)

View File

@ -4,11 +4,13 @@ namespace AppBundle\Service\Loader;
use AppBundle\Entity\LDraw\Model; use AppBundle\Entity\LDraw\Model;
use AppBundle\Service\Stl\StlRendererService; use AppBundle\Service\Stl\StlRendererService;
use League\Flysystem\Filesystem; use Doctrine\ORM\EntityManagerInterface;
use League\Flysystem\FilesystemInterface;
use Psr\Log\LoggerInterface;
class ImageLoader extends BaseLoader class ImageLoader extends BaseLoader
{ {
/** @var Filesystem */ /** @var FilesystemInterface */
private $mediaFilesystem; private $mediaFilesystem;
/** @var string */ /** @var string */
@ -17,11 +19,13 @@ class ImageLoader extends BaseLoader
/** @var StlRendererService */ /** @var StlRendererService */
private $stlRendererService; private $stlRendererService;
public function __construct($mediaFilesystem, $rebrickableDownloadUrl, $stlRendererService) public function __construct(EntityManagerInterface $em, LoggerInterface $logger, FilesystemInterface $mediaFilesystem, $rebrickableDownloadUrl, StlRendererService $stlRendererService)
{ {
$this->mediaFilesystem = $mediaFilesystem; $this->mediaFilesystem = $mediaFilesystem;
$this->rebrickableDownloadUrl = $rebrickableDownloadUrl; $this->rebrickableDownloadUrl = $rebrickableDownloadUrl;
$this->stlRendererService = $stlRendererService; $this->stlRendererService = $stlRendererService;
parent::__construct($em, $logger);
} }
/** /**

View File

@ -10,15 +10,17 @@ use AppBundle\Entity\LDraw\Model;
use AppBundle\Entity\LDraw\Subpart; use AppBundle\Entity\LDraw\Subpart;
use AppBundle\Exception\ConvertingFailedException; use AppBundle\Exception\ConvertingFailedException;
use AppBundle\Exception\FileException; use AppBundle\Exception\FileException;
use AppBundle\Exception\MissingContextException; use AppBundle\Exception\Loader\MissingContextException;
use AppBundle\Exception\ParseErrorException; use AppBundle\Exception\ParseErrorException;
use AppBundle\Repository\LDraw\ModelRepository; use AppBundle\Repository\LDraw\ModelRepository;
use AppBundle\Service\Stl\StlConverterService; use AppBundle\Service\Stl\StlConverterService;
use AppBundle\Util\LDModelParser; use AppBundle\Util\LDModelParser;
use AppBundle\Util\RelationMapper; use AppBundle\Util\RelationMapper;
use Doctrine\ORM\EntityManagerInterface;
use League\Flysystem\Adapter\Local; use League\Flysystem\Adapter\Local;
use League\Flysystem\Exception; use League\Flysystem\Exception;
use League\Flysystem\Filesystem; use League\Flysystem\Filesystem;
use Psr\Log\LoggerInterface;
class ModelLoader extends BaseLoader class ModelLoader extends BaseLoader
{ {
@ -50,16 +52,20 @@ class ModelLoader extends BaseLoader
private $rewrite = false; private $rewrite = false;
/** /**
* LDrawLoaderService constructor. * ModelLoader constructor.
* *
* @param StlConverterService $stlConverter * @param EntityManagerInterface $em
* @param RelationMapper $relationMapper * @param LoggerInterface $logger
* @param StlConverterService $stlConverter
* @param RelationMapper $relationMapper
*/ */
public function __construct($stlConverter, $relationMapper) public function __construct(EntityManagerInterface $em, LoggerInterface $logger, StlConverterService $stlConverter, RelationMapper $relationMapper)
{ {
$this->stlConverter = $stlConverter; $this->stlConverter = $stlConverter;
$this->relationMapper = $relationMapper; $this->relationMapper = $relationMapper;
$this->ldModelParser = new LDModelParser(); $this->ldModelParser = new LDModelParser();
parent::__construct($em, $logger);
} }
/** /**
@ -71,7 +77,7 @@ class ModelLoader extends BaseLoader
} }
/** /**
* @param $ldrawLibrary * @param string $ldrawLibrary
*/ */
public function setLDrawLibraryContext($ldrawLibrary) public function setLDrawLibraryContext($ldrawLibrary)
{ {

View File

@ -4,7 +4,9 @@ namespace AppBundle\Service\Loader;
use AppBundle\Entity\Rebrickable\Part; use AppBundle\Entity\Rebrickable\Part;
use AppBundle\Entity\Rebrickable\Set; use AppBundle\Entity\Rebrickable\Set;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\Query\Expr\Join;
use Psr\Log\LoggerInterface;
//TODO Refactor + validate csv files //TODO Refactor + validate csv files
class RebrickableLoader extends BaseLoader class RebrickableLoader extends BaseLoader
@ -14,11 +16,17 @@ class RebrickableLoader extends BaseLoader
private $csvFile; private $csvFile;
/** /**
* ModelLoaderService constructor. * RebrickableLoader constructor.
*
* @param EntityManagerInterface $em
* @param LoggerInterface $logger
* @param $rebrickableDownloadUrl
*/ */
public function __construct($rebrickable_url) public function __construct(EntityManagerInterface $em, LoggerInterface $logger, $rebrickableDownloadUrl)
{ {
$this->rebrickable_url = $rebrickable_url; $this->rebrickable_url = $rebrickableDownloadUrl;
parent::__construct($em, $logger);
} }
public function loadAll() public function loadAll()

View File

@ -7,6 +7,8 @@ use AppBundle\Entity\Rebrickable\Part;
use AppBundle\Repository\LDraw\ModelRepository; use AppBundle\Repository\LDraw\ModelRepository;
use AppBundle\Repository\Rebrickable\PartRepository; use AppBundle\Repository\Rebrickable\PartRepository;
use AppBundle\Util\RelationMapper; use AppBundle\Util\RelationMapper;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
class RelationLoader extends BaseLoader class RelationLoader extends BaseLoader
{ {
@ -22,15 +24,17 @@ class RelationLoader extends BaseLoader
/** /**
* RelationLoader constructor. * RelationLoader constructor.
* *
* @param RelationMapper $relationMapper * @param EntityManagerInterface $em
* @param ModelRepository $modelRepository * @param LoggerInterface $logger
* @param PartRepository $partRepository * @param RelationMapper $relationMapper
*/ */
public function __construct($relationMapper, $modelRepository, $partRepository) public function __construct(EntityManagerInterface $em, LoggerInterface $logger, RelationMapper $relationMapper)
{ {
$this->relationMapper = $relationMapper; $this->relationMapper = $relationMapper;
$this->modelRepository = $modelRepository; $this->modelRepository = $em->getRepository(Model::class);
$this->partRepository = $partRepository; $this->partRepository = $em->getRepository(Part::class);
parent::__construct($em, $logger);
} }
public function loadAll() public function loadAll()

View File

@ -3,19 +3,46 @@
namespace AppBundle\Service; namespace AppBundle\Service;
use AppBundle\Entity\LDraw\Model; use AppBundle\Entity\LDraw\Model;
use AppBundle\Repository\LDraw\ModelRepository;
use Doctrine\ORM\EntityManagerInterface;
class ModelService class ModelService
{ {
private $models = []; private $models = [];
/** @var ModelRepository */
private $modelRepository;
/** /**
* Get all subparts of model * ModelService constructor.
*
* @param EntityManagerInterface $em
*/
public function __construct(EntityManagerInterface $em)
{
$this->modelRepository = $em->getRepository(Model::class);
}
/**
* Find model by id or alias number.
*
* @param $id
*
* @return Model|null
*/
public function findModel($id)
{
return $this->modelRepository->findOneByNumber($id);
}
/**
* Get all subparts of model.
* *
* @param Model $model * @param Model $model
*
* @return array * @return array
*/ */
public function getAllSubparts(Model $model) public function getSubmodels(Model $model)
{ {
foreach ($model->getSubparts() as $subpart) { foreach ($model->getSubparts() as $subpart) {
$this->resursiveLoadModels($subpart->getSubpart(), $subpart->getCount()); $this->resursiveLoadModels($subpart->getSubpart(), $subpart->getCount());
@ -24,6 +51,28 @@ class ModelService
return $this->models; return $this->models;
} }
/**
* Get all siblings of model.
*
* @param Model $model
*
* @return array
*/
public function getSiblings(Model $model)
{
$this->modelRepository->findAllRelatedModels($model);
}
/**
* Get total count of models in database.
*
* @return mixed
*/
public function getTotalCount()
{
return $this->modelRepository->count();
}
private function resursiveLoadModels(Model $model, $quantity = 1) private function resursiveLoadModels(Model $model, $quantity = 1)
{ {
if (($model->getSubparts()->count() !== 0)) { if (($model->getSubparts()->count() !== 0)) {

View File

@ -4,189 +4,253 @@ namespace AppBundle\Service;
use AppBundle\Entity\LDraw\Model; use AppBundle\Entity\LDraw\Model;
use AppBundle\Entity\Rebrickable\Inventory_Part; use AppBundle\Entity\Rebrickable\Inventory_Part;
use AppBundle\Entity\Rebrickable\Inventory_Set;
use AppBundle\Entity\Rebrickable\Part;
use AppBundle\Entity\Rebrickable\Set; use AppBundle\Entity\Rebrickable\Set;
use AppBundle\Repository\Rebrickable\Inventory_PartRepository; use AppBundle\Repository\Rebrickable\Inventory_PartRepository;
use AppBundle\Repository\Rebrickable\Inventory_SetRepository;
use AppBundle\Repository\Rebrickable\SetRepository;
use Doctrine\ORM\EntityManagerInterface;
class SetService class SetService
{ {
/** @var SetRepository */
private $setRepository;
/** @var Inventory_PartRepository */ /** @var Inventory_PartRepository */
private $inventoryPartRepository; private $inventoryPartRepository;
/** /** @var Inventory_SetRepository */
* SetService constructor. private $inventorySetRepository;
*
* @param Inventory_PartRepository $inventoryPartRepository
*/
public function __construct(Inventory_PartRepository $inventoryPartRepository)
{
$this->inventoryPartRepository = $inventoryPartRepository;
}
/** /**
* Get array of all known models in the kit(set) with quantity. Ignores colors and groups parts with the same shape. * SetService constructor.
* [ *
* modelNumber => [ * @param EntityManagerInterface $em
* 'model' => Model, */
* 'quantity => int public function __construct(EntityManagerInterface $em)
* ] {
* ... $this->setRepository = $em->getRepository(Set::class);
* ]. $this->inventoryPartRepository = $em->getRepository(Inventory_Part::class);
* $this->inventorySetRepository = $em->getRepository(Inventory_Set::class);
* @param Set $set }
* @param bool $spare If true - add only spare parts, false - add only regular parts, null - add all parts
*
* @return array
*/
public function getModels(Set $set, $spare = null)
{
$models = [];
$inventoryParts = $this->inventoryPartRepository->findAllBySetNumber($set->getId(), $spare, true); /**
* Get all sets in the set inventory.
*
* @param Set $set
*
* @return array|null
*/
public function getAllSubSets(Set $set)
{
return $this->inventorySetRepository->findAllBySetNumber($set->getId());
}
/** @var Inventory_Part $inventoryPart */ /**
foreach ($inventoryParts as $inventoryPart) { * Get all sets in which the model appears.
if ($model = $inventoryPart->getPart()->getModel()) { *
if (isset($models[$model->getId()])) { * @param Model $model
$models[$model->getId()]['quantity'] += $inventoryPart->getQuantity(); *
} else { * @return array
$models[$model->getId()] = [ */
'model' => $model, public function getAllByModel(Model $model)
'quantity' => $inventoryPart->getQuantity(), {
]; return $this->setRepository->findAllByModel($model);
} }
}
}
return $models; /**
} * Get all sets in which the model appears.
*
* @param Part $part
*
* @return array
*/
public function getAllByPart(Part $part)
{
return $this->setRepository->findAllByPart($part);
}
/** /**
* Get array of all known models in the kit(set). * Get total count of sets in database.
* [ *
* modelNumber => [ * @return int
* 'model' => Model, */
* 'colors => [ public function getTotalCount()
* colorID => [ {
* 'color' => Color, return $this->setRepository->count();
* 'quantity => int }
* ]
* ...
* ]
* ]
* ...
* ].
*
* @param Set $set
* @param bool $spare If true - add only spare parts, false - add only regular parts, null - add all parts
*
* @return array
*/
public function getModelsWithColors(Set $set, $spare = null)
{
$models = [];
$inventoryParts = $this->inventoryPartRepository->findAllBySetNumber($set->getId(), $spare, true); public function getPartCount(Set $set, $spare = null, $model = null)
{
return $this->inventoryPartRepository->getPartCount($set, $spare, $model);
}
/** @var Inventory_Part $inventoryPart */ /**
foreach ($inventoryParts as $inventoryPart) { * Get array of all known models in the kit(set) with quantity. Ignores colors and groups parts with the same shape.
if ($model = $inventoryPart->getPart()->getModel()) { * [
$color = $inventoryPart->getColor(); * modelNumber => [
* 'model' => Model,
* 'quantity => int
* ]
* ...
* ].
*
* @param Set $set
* @param bool $spare If true - add only spare parts, false - add only regular parts, null - add all parts
*
* @return array
*/
public function getModels(Set $set, $spare = null)
{
$models = [];
if (!isset($models[$model->getId()]['model'])) { $inventoryParts = $this->inventoryPartRepository->findAllBySetNumber($set->getId(), $spare, true);
$models[$model->getId()]['model'] = $model;
}
if (isset($models[$model->getId()]['colors'][$color->getId()])) { /** @var Inventory_Part $inventoryPart */
$models[$model->getId()]['colors'][$color->getId()]['quantity'] += $inventoryPart->getQuantity(); foreach ($inventoryParts as $inventoryPart) {
} else { if ($model = $inventoryPart->getPart()->getModel()) {
$models[$model->getId()]['colors'][$color->getId()] = [ if (isset($models[$model->getId()])) {
'color' => $color, $models[$model->getId()]['quantity'] += $inventoryPart->getQuantity();
'quantity' => $inventoryPart->getQuantity(),
];
}
}
}
return $models;
}
/**
* Get array models grouped by color.
* [
* 'colorID' => [
* 'color' => Color,
* 'models => [
* modelNumber => [
* 'model' => Model,
* 'quantity' => int
* ]
* ...
* ]
* ]
* ...
* ].
*
* @param Set $set
* @param bool $spare If true - add only spare parts, false - add only regular parts, null - add all parts
*
* @return array
*/
public function getModelsGroupedByColor(Set $set, $spare = null)
{
$colors = [];
$inventoryParts = $this->inventoryPartRepository->findAllBySetNumber($set->getId(), $spare, true);
/** @var Inventory_Part $inventoryPart */
foreach ($inventoryParts as $inventoryPart) {
if ($model = $inventoryPart->getPart()->getModel()) {
$color = $inventoryPart->getCOlor();
if (!isset($colors[$color->getId()]['color'])) {
$colors[$color->getId()]['color'] = $color;
$colors[$color->getId()]['quantity'] = 0;
}
$colors[$color->getId()]['quantity'] += $inventoryPart->getQuantity();
if (isset($colors[$color->getId()]['models'][$model->getId()])) {
$colors[$color->getId()]['models'][$model->getId()]['quantity'] += $inventoryPart->getQuantity();
} else {
$colors[$color->getId()]['models'][$model->getId()] = [
'model' => $model,
'quantity' => $inventoryPart->getQuantity(),
];
}
}
}
return $colors;
}
/*
* @param Set $set
* @param bool $spare If true - add only spare parts, false - add only regular parts, null - add all parts
*
* @return array
*/
public function getParts(Set $set, $spare = null, $model = false)
{
$parts = [];
$inventoryParts = $this->inventoryPartRepository->findAllBySetNumber($set->getId(), $spare, $model);
/** @var Inventory_Part $inventoryPart */
foreach ($inventoryParts as $inventoryPart) {
if (isset($parts[$inventoryPart->getPart()->getId()])) {
$parts[$inventoryPart->getPart()->getId()]['quantity'] += $inventoryPart->getQuantity();
} else { } else {
$parts[$inventoryPart->getPart()->getId()] = [ $models[$model->getId()] = [
'part' => $inventoryPart->getPart(), 'model' => $model,
'quantity' => $inventoryPart->getQuantity(), 'quantity' => $inventoryPart->getQuantity(),
]; ];
} }
} }
return $parts;
} }
return $models;
}
/**
* Get array of all known models in the kit(set).
* [
* modelNumber => [
* 'model' => Model,
* 'colors => [
* colorID => [
* 'color' => Color,
* 'quantity => int
* ]
* ...
* ]
* ]
* ...
* ].
*
* @param Set $set
* @param bool $spare If true - add only spare parts, false - add only regular parts, null - add all parts
*
* @return array
*/
public function getModelsWithColors(Set $set, $spare = null)
{
$models = [];
$inventoryParts = $this->inventoryPartRepository->findAllBySetNumber($set->getId(), $spare, true);
/** @var Inventory_Part $inventoryPart */
foreach ($inventoryParts as $inventoryPart) {
if ($model = $inventoryPart->getPart()->getModel()) {
$color = $inventoryPart->getColor();
if (!isset($models[$model->getId()]['model'])) {
$models[$model->getId()]['model'] = $model;
}
if (isset($models[$model->getId()]['colors'][$color->getId()])) {
$models[$model->getId()]['colors'][$color->getId()]['quantity'] += $inventoryPart->getQuantity();
} else {
$models[$model->getId()]['colors'][$color->getId()] = [
'color' => $color,
'quantity' => $inventoryPart->getQuantity(),
];
}
}
}
return $models;
}
/**
* Get array models grouped by color.
* [
* 'colorID' => [
* 'color' => Color,
* 'models => [
* modelNumber => [
* 'model' => Model,
* 'quantity' => int
* ]
* ...
* ]
* ]
* ...
* ].
*
* @param Set $set
* @param bool $spare If true - add only spare parts, false - add only regular parts, null - add all parts
*
* @return array
*/
public function getModelsGroupedByColor(Set $set, $spare = null)
{
$colors = [];
$inventoryParts = $this->inventoryPartRepository->findAllBySetNumber($set->getId(), $spare, true);
/** @var Inventory_Part $inventoryPart */
foreach ($inventoryParts as $inventoryPart) {
if ($model = $inventoryPart->getPart()->getModel()) {
$color = $inventoryPart->getCOlor();
if (!isset($colors[$color->getId()]['color'])) {
$colors[$color->getId()]['color'] = $color;
$colors[$color->getId()]['quantity'] = 0;
}
$colors[$color->getId()]['quantity'] += $inventoryPart->getQuantity();
if (isset($colors[$color->getId()]['models'][$model->getId()])) {
$colors[$color->getId()]['models'][$model->getId()]['quantity'] += $inventoryPart->getQuantity();
} else {
$colors[$color->getId()]['models'][$model->getId()] = [
'model' => $model,
'quantity' => $inventoryPart->getQuantity(),
];
}
}
}
return $colors;
}
/*
* @param Set $set
* @param bool $spare If true - add only spare parts, false - add only regular parts, null - add all parts
*
* @return array
*/
public function getParts(Set $set, $spare = null, $model = false)
{
$parts = [];
$inventoryParts = $this->inventoryPartRepository->findAllBySetNumber($set->getId(), $spare, $model);
/** @var Inventory_Part $inventoryPart */
foreach ($inventoryParts as $inventoryPart) {
if (isset($parts[$inventoryPart->getPart()->getId()])) {
$parts[$inventoryPart->getPart()->getId()]['quantity'] += $inventoryPart->getQuantity();
} else {
$parts[$inventoryPart->getPart()->getId()] = [
'part' => $inventoryPart->getPart(),
'quantity' => $inventoryPart->getQuantity(),
];
}
}
return $parts;
}
} }

View File

@ -39,7 +39,7 @@ class StlConverterService
* @param FilesystemInterface $mediaFilesystem Filesystem for generated web assets * @param FilesystemInterface $mediaFilesystem Filesystem for generated web assets
* @param StlFixerService $stlFixer * @param StlFixerService $stlFixer
*/ */
public function __construct($ldview, $mediaFilesystem, $stlFixer) public function __construct($ldview, FilesystemInterface $mediaFilesystem, StlFixerService $stlFixer)
{ {
$this->ldview = $ldview; $this->ldview = $ldview;
$this->mediaFilesystem = $mediaFilesystem; $this->mediaFilesystem = $mediaFilesystem;
@ -47,9 +47,9 @@ class StlConverterService
} }
/** /**
* @param string $ldrawLibraryContext * @param FilesystemInterface $ldrawLibraryContext
*/ */
public function setLDrawLibraryContext($ldrawLibraryContext) public function setLDrawLibraryContext(FilesystemInterface $ldrawLibraryContext)
{ {
$this->ldrawLibraryContext = $ldrawLibraryContext; $this->ldrawLibraryContext = $ldrawLibraryContext;
} }

View File

@ -38,9 +38,10 @@ class StlRendererService
/** /**
* StlRendererService constructor. * StlRendererService constructor.
* *
* @param $layout * @param string $layout
* @param $povray * @param string $povray
* @param $stl2pov * @param string $stl2pov
* @param string $tmpDir
*/ */
public function __construct($layout, $povray, $stl2pov, $tmpDir = null) public function __construct($layout, $povray, $stl2pov, $tmpDir = null)
{ {

View File

@ -20,17 +20,20 @@ class ZipService
/** @var ModelService */ /** @var ModelService */
private $modelService; private $modelService;
/** @var string */
private $zipName; private $zipName;
private $models; /** @var array */
private $models = [];
/** /**
* ZipService constructor. * ZipService constructor.
* *
* @param $mediaFilesystem * @param Filesystem $mediaFilesystem
* @param $setService * @param ModelService $modelService
* @param SetService $setService
*/ */
public function __construct($mediaFilesystem, $setService, $modelService) public function __construct(Filesystem $mediaFilesystem, ModelService $modelService, SetService $setService)
{ {
$this->mediaFilesystem = $mediaFilesystem; $this->mediaFilesystem = $mediaFilesystem;
$this->setService = $setService; $this->setService = $setService;
@ -46,11 +49,12 @@ class ZipService
} }
/** /**
* Create zip archive with models in set in temp dir * Create zip archive with models in set in temp dir.
* *
* @param Set $set * @param Set $set
* @param string $filename Filename of archive base directory * @param string $filename Filename of archive base directory
* @param bool $sorted Sort models into folders by color * @param bool $sorted Sort models into folders by color
*
* @return bool|string * @return bool|string
*/ */
public function createFromSet(Set $set, $filename, $sorted = false) public function createFromSet(Set $set, $filename, $sorted = false)
@ -73,11 +77,12 @@ class ZipService
} }
/** /**
* Create zip archive of model in temp dir * Create zip archive of model in temp dir.
* *
* @param Model $model * @param Model $model
* @param string $filename Filename of archive base directory * @param string $filename Filename of archive base directory
* @param bool $subparts Include directory with subparts into archive * @param bool $subparts Include directory with subparts into archive
*
* @return bool|string * @return bool|string
*/ */
public function createFromModel(Model $model, $filename, $subparts = false) public function createFromModel(Model $model, $filename, $subparts = false)
@ -91,7 +96,7 @@ class ZipService
$this->addModel($filename, $model); $this->addModel($filename, $model);
if ($subparts) { if ($subparts) {
foreach ($this->modelService->getAllSubparts($model) as $subpart) { foreach ($this->modelService->getSubmodels($model) as $subpart) {
$submodel = $subpart['model']; $submodel = $subpart['model'];
$filename = "{$this->zipName}/submodels/{$submodel->getId()}_({$subpart['quantity']}x).stl"; $filename = "{$this->zipName}/submodels/{$submodel->getId()}_({$subpart['quantity']}x).stl";
@ -155,9 +160,8 @@ class ZipService
$this->models[$model->getId()] = $model; $this->models[$model->getId()] = $model;
} }
/** /**
* Add LICENSE.txt file to archive * Add LICENSE.txt file to archive.
*/ */
private function addLicense() private function addLicense()
{ {

View File

@ -14,7 +14,7 @@ class AppExtension extends \Twig_Extension
* *
* @param FormatTransformer $formatTransformer * @param FormatTransformer $formatTransformer
*/ */
public function __construct($formatTransformer) public function __construct(FormatTransformer $formatTransformer)
{ {
$this->formatTransformer = $formatTransformer; $this->formatTransformer = $formatTransformer;
} }