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 {
padding-left: 30px;
position: relative;
display: inline-block;
margin: 0.2em 1em;
}
.link:before {

View File

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

View File

@ -11,7 +11,7 @@ set:
models:
text: |
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:
credit: |
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:
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

@ -107,3 +107,28 @@
{% include 'footer.html.twig' %}
</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 %}

View File

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

View File

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

View File

@ -59,20 +59,18 @@
{{ brset.rating | number_format(1, '.', ',') }} / 5
</td>
</tr>
<tr>
<td></td>
<td>
<a class="brickset link" href="{{ brset.bricksetURL }}">Brickset</a>
</td>
</tr>
{% endif %}
<tr>
<td></td>
<td>
<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>
</tr>
</table>
<div class="addthis_inline_share_toolbox"></div>
</div>
</div>
</div>

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:
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:
- { resource: service/repository.yml }
- { resource: service/api.yml }
- { resource: service/loader.yml }
- { resource: service/util.yml }
- { resource: service/service.yml }
- { resource: service/form.yml }
- { resource: service/legacy_aliases.yml }
- { resource: service/menu.yml }
services:
# default configuration for services in *this* file
_defaults:
# 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\CallFailedException;
class Brickset
class BricksetClient
{
const WSDL = 'https://brickset.com/api/v2.asmx?WSDL';
@ -40,14 +40,16 @@ class Brickset
];
/**
* BricksetClient constructor.
*
* @param string $apikey Brickset API key
* @param array $options A array of config values
*
* @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['exceptions'] = true;
@ -59,14 +61,15 @@ class Brickset
}
}
/**
* Get or create new SoapClient
* Get or create new SoapClient.
*
* @throws ApiException
*
* @return \SoapClient
* @throws ApiException
*/
private function getSoapClient() {
private function getSoapClient()
{
if (!$this->soapClient) {
try {
$this->soapClient = new \SoapClient(self::WSDL, $this->options);
@ -80,6 +83,7 @@ class Brickset
throw new ApiException(ApiException::BRICKSET);
}
}
return $this->soapClient;
}

View File

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

View File

@ -2,13 +2,13 @@
namespace AppBundle\Api\Manager;
use AppBundle\Api\Client\Brickset\Brickset;
use AppBundle\Api\Client\Brickset\BricksetClient;
use Doctrine\Common\Cache\CacheProvider;
class BricksetManager
{
/**
* @var Brickset
* @var BricksetClient
*/
private $bricksetClient;
@ -19,10 +19,10 @@ class BricksetManager
/**
* BricksetManager constructor.
*
* @param Brickset $bricksetClient
* @param BricksetClient $bricksetClient
* @param CacheProvider $cache
*/
public function __construct(Brickset $bricksetClient, CacheProvider $cache)
public function __construct(BricksetClient $bricksetClient, CacheProvider $cache)
{
$this->bricksetClient = $bricksetClient;
$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\Set;
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\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
@ -19,7 +19,7 @@ class RebrickableManager
const FORMAT = 'json';
/**
* @var Rebrickable_v3
* @var RebrickableClient
*/
private $rebrickableClient;
@ -31,9 +31,9 @@ class RebrickableManager
/**
* RebrickableManager constructor.
*
* @param Rebrickable_v3 $rebrickableClient
* @param RebrickableClient $rebrickableClient
*/
public function __construct(Rebrickable_v3 $rebrickableClient)
public function __construct(RebrickableClient $rebrickableClient)
{
$this->rebrickableClient = $rebrickableClient;
$this->serializer = $this->initSerializer();
@ -176,7 +176,6 @@ class RebrickableManager
$response = $this->rebrickableClient->call('GET', 'lego/sets/'.$setId.'/parts', $options);
$data = json_decode($response, true)['results'];
return $this->serializer->denormalize($data, Part::class.'[]', self::FORMAT);
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -2,13 +2,12 @@
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\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"=".+"})
@ -19,7 +18,7 @@ class AjaxController extends Controller
$session->set('tab', $tab);
$response = new Response();
return $response;
return $response;
}
}

View File

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

View File

@ -2,7 +2,10 @@
namespace AppBundle\Controller;
use AppBundle\Entity\Color;
use AppBundle\Service\ColorService;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
/**
@ -10,17 +13,15 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller;
*
* @Route("colors")
*/
class ColorController extends Controller
class ColorController extends AbstractController
{
/**
* @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', [
'colors' => $colors,
'colors' => $colorService->getAll(),
]);
}
}

View File

@ -2,28 +2,21 @@
namespace AppBundle\Controller;
use AppBundle\Repository\LDraw\ModelRepository;
use AppBundle\Repository\Rebrickable\SetRepository;
use AppBundle\Service\ModelService;
use AppBundle\Service\SetService;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class DefaultController extends Controller
class DefaultController extends AbstractController
{
/**
* @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', [
'models' => $modelRepository->count(),
'sets' => $setRepository->count(),
'models' => $modelService->getTotalCount(),
'sets' => $setService->getTotalCount(),
]);
}
}

View File

@ -2,6 +2,7 @@
namespace AppBundle\Controller;
use League\Flysystem\Filesystem;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
@ -19,10 +20,8 @@ class MediaController extends Controller
*
* @return Response
*/
public function fileAction($path)
public function fileAction($path, Filesystem $mediaFilesystem)
{
$mediaFilesystem = $this->get('oneup_flysystem.media_filesystem');
if ($mediaFilesystem->has($path)) {
$response = new BinaryFileResponse($mediaFilesystem->getAdapter()->getPathPrefix().DIRECTORY_SEPARATOR.$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\Form\Search\ModelSearchType;
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 Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
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\Request;
use Symfony\Component\HttpFoundation\Response;
@ -28,11 +30,11 @@ class ModelController extends Controller
*
* @Route("/", name="model_index")
*/
public function indexAction(Request $request)
public function indexAction(Request $request, FormFactoryInterface $formFactory)
{
$modelSearch = new ModelSearch();
$form = $this->get('form.factory')->createNamedBuilder('', ModelSearchType::class, $modelSearch)->getForm();
$form = $formFactory->createNamedBuilder('', ModelSearchType::class, $modelSearch)->getForm();
$form->handleRequest($request);
$elasticaManager = $this->get('fos_elastica.manager');
@ -58,21 +60,14 @@ class ModelController extends Controller
* @Route("/{id}", name="model_detail")
* @Method("GET")
*/
public function detailAction($id)
public function detailAction($id, ModelService $modelService)
{
/** @var Model $model */
if ($model = $this->get('repository.ldraw.model')->findOneByNumber($id)) {
if ($model = $modelService->findModel($id)) {
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', [
'model' => $model,
'sets' => $sets,
'related' => $related,
'subparts' => $subparts,
'siblings' => $modelService->getSiblings($model),
'submodels' => $modelService->getSubmodels($model),
]);
} catch (\Exception $e) {
$this->addFlash('error', $e->getMessage());
@ -82,21 +77,49 @@ class ModelController extends Controller
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")
* @Method("GET")
*/
public function zipAction(Request $request, Model $model)
public function zipAction(Model $model, ZipService $zipService)
{
// escape forbidden characters from filename
$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->headers->set('Content-Type', 'application/zip');
// Create the disposition of the file
$disposition = $response->headers->makeDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,

View File

@ -3,9 +3,14 @@
namespace AppBundle\Controller;
use AppBundle\Api\Exception\EmptyResponseException;
use AppBundle\Api\Manager\RebrickableManager;
use AppBundle\Entity\Rebrickable\Part;
use AppBundle\Service\SetService;
use Knp\Component\Pager\Paginator;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Part controller.
@ -19,7 +24,7 @@ class PartController extends Controller
*
* @Route("/{id}", name="part_detail")
*/
public function detailAction(Part $part)
public function detailAction(Part $part, RebrickableManager $rebrickableManager)
{
$apiPart = null;
if ($part) {
@ -28,7 +33,7 @@ class PartController extends Controller
}
try {
$apiPart = $this->get('api.manager.rebrickable')->getPart($part->getId());
$apiPart = $rebrickableManager->getPart($part->getId());
} catch (EmptyResponseException $e) {
$this->addFlash('warning', 'Part not found');
} catch (\Exception $e) {
@ -43,4 +48,32 @@ class PartController extends Controller
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;
use AppBundle\Api\Exception\ApiException;
use AppBundle\Entity\Rebrickable\Inventory_Set;
use AppBundle\Api\Manager\BricksetManager;
use AppBundle\Entity\Rebrickable\Set;
use AppBundle\Form\Search\SetSearchType;
use AppBundle\Model\SetSearch;
use AppBundle\Repository\Rebrickable\Inventory_PartRepository;
use AppBundle\Repository\Search\SetRepository;
use AppBundle\Service\SetService;
use AppBundle\Service\ZipService;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@ -24,12 +25,16 @@ class SetController extends Controller
{
/**
* @Route("/", name="set_index")
*
* @param Request $request
*
* @return Response
*/
public function indexAction(Request $request)
public function indexAction(Request $request, FormFactoryInterface $formFactory)
{
$setSearch = new SetSearch();
$form = $this->get('form.factory')->createNamedBuilder('', SetSearchType::class, $setSearch)->getForm();
$form = $formFactory->createNamedBuilder('', SetSearchType::class, $setSearch)->getForm();
$form->handleRequest($request);
/** @var SetRepository $setRepository */
@ -51,19 +56,17 @@ class SetController extends Controller
/**
* @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;
$partCount = $inventoryPartRepository->getPartCount($set, false);
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");
}
} catch (ApiException $e) {
@ -75,33 +78,22 @@ class SetController extends Controller
return $this->render('set/detail.html.twig', [
'set' => $set,
'brset' => $bricksetSet,
'partCount' => $partCount,
'partCount' => $setService->getPartCount($set),
]);
}
/**
* @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', [
'inventorySets' => $inventorySets,
'inventorySets' => $setService->getAllSubSets($set),
'set' => $set,
'missing' => $missing,
'models' => $models,
'missingCount' => $missingCount,
'partCount' => $partCount,
'missing' => $setService->getParts($set, false, false),
'models' => $setService->getModels($set, false),
'missingCount' => $setService->getPartCount($set, false, false),
'partCount' => $setService->getPartCount($set, false),
]);
if ($request->isXmlHttpRequest()) {
@ -118,10 +110,8 @@ class SetController extends Controller
/**
* @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;
$missing = null;
@ -152,11 +142,8 @@ class SetController extends Controller
/**
* @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;
$missing = null;
@ -187,14 +174,14 @@ class SetController extends Controller
/**
* @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;
$sort = $sorted ? 'Multi-Color' : 'Uni-Color';
// escape forbidden characters from filename
$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->headers->set('Content-Type', 'application/zip');

View File

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

View File

@ -5,6 +5,7 @@ namespace AppBundle\Form\Search;
use AppBundle\Entity\LDraw\Category;
use AppBundle\Model\ModelSearch;
use AppBundle\Repository\LDraw\CategoryRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
@ -16,9 +17,14 @@ class ModelSearchType extends AbstractType
/** @var 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)

View File

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

View File

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

View File

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

View File

@ -4,6 +4,7 @@ namespace AppBundle\Imagine;
use AppBundle\Api\Manager\BricksetManager;
use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemInterface;
use Liip\ImagineBundle\Exception\Binary\Loader\NotLoadableException;
class SetImageLoader extends BaseImageLoader
@ -19,9 +20,10 @@ class SetImageLoader extends BaseImageLoader
/**
* 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->mediaFilesystem = $mediaFilesystem;

View File

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

View File

@ -48,6 +48,14 @@ class Inventory_PartRepository extends BaseRepository
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)
{
$inventory = $this->getEntityManager()->getRepository(Inventory::class)->findNewestInventoryBySetNumber($number);
@ -61,6 +69,15 @@ class Inventory_PartRepository extends BaseRepository
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)
{
$inventory = $this->getEntityManager()->getRepository(Inventory::class)->findNewestInventoryBySetNumber($set->getId());

View File

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

View File

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

View File

@ -9,7 +9,7 @@ use FOS\ElasticaBundle\Repository;
class ModelRepository extends Repository
{
/**
* Create search query from ModelSearch entity
* Create search query from ModelSearch entity.
*
* @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 int $limit
*
* @return mixed
*/
public function findHighlighted($query, $limit = 500)

View File

@ -10,13 +10,12 @@ use Elastica\Query\Range;
use FOS\ElasticaBundle\Repository;
/**
* Class SetRepository
* @package AppBundle\Repository\Search
* Class SetRepository.
*/
class SetRepository extends Repository
{
/**
* Create search query from SetSearch entity
* Create search query from SetSearch entity.
*
* @param SetSearch $setSearch
*
@ -71,6 +70,7 @@ class SetRepository extends Repository
/**
* @param SetSearch $setSearch
* @param int $limit
*
* @return array
*/
public function search(SetSearch $setSearch, $limit = 500)
@ -80,12 +80,12 @@ class SetRepository extends Repository
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 int $limit
*
* @return mixed
*/
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\Transformer\FormatTransformer;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Monolog\Logger;
use Symfony\Bundle\FrameworkBundle\Translation\Translator;
use Psr\Log\LoggerInterface;
use Symfony\Component\Asset\Exception\LogicException;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Output\OutputInterface;
@ -41,19 +42,16 @@ abstract class BaseLoader
private $formatTransformer;
/**
* Loader constructor.
* BaseLoader constructor.
*
* @param EntityManager $em
* @param Logger $logger
* @param Translator $formatTransformer
* @param EntityManagerInterface $em
* @param LoggerInterface $logger
*/
public function setArguments(EntityManager $em, $logger, $formatTransformer)
public function __construct(EntityManagerInterface $em, LoggerInterface $logger)
{
$this->em = $em;
$this->em->getConnection()->getConfiguration()->setSQLLogger(null);
$this->logger = $logger;
$this->formatTransformer = $formatTransformer;
$this->formatTransformer = new FormatTransformer();
}
public function setOutput(OutputInterface $output)

View File

@ -4,11 +4,13 @@ namespace AppBundle\Service\Loader;
use AppBundle\Entity\LDraw\Model;
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
{
/** @var Filesystem */
/** @var FilesystemInterface */
private $mediaFilesystem;
/** @var string */
@ -17,11 +19,13 @@ class ImageLoader extends BaseLoader
/** @var 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->rebrickableDownloadUrl = $rebrickableDownloadUrl;
$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\Exception\ConvertingFailedException;
use AppBundle\Exception\FileException;
use AppBundle\Exception\MissingContextException;
use AppBundle\Exception\Loader\MissingContextException;
use AppBundle\Exception\ParseErrorException;
use AppBundle\Repository\LDraw\ModelRepository;
use AppBundle\Service\Stl\StlConverterService;
use AppBundle\Util\LDModelParser;
use AppBundle\Util\RelationMapper;
use Doctrine\ORM\EntityManagerInterface;
use League\Flysystem\Adapter\Local;
use League\Flysystem\Exception;
use League\Flysystem\Filesystem;
use Psr\Log\LoggerInterface;
class ModelLoader extends BaseLoader
{
@ -50,16 +52,20 @@ class ModelLoader extends BaseLoader
private $rewrite = false;
/**
* LDrawLoaderService constructor.
* ModelLoader constructor.
*
* @param EntityManagerInterface $em
* @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->relationMapper = $relationMapper;
$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)
{

View File

@ -4,7 +4,9 @@ namespace AppBundle\Service\Loader;
use AppBundle\Entity\Rebrickable\Part;
use AppBundle\Entity\Rebrickable\Set;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query\Expr\Join;
use Psr\Log\LoggerInterface;
//TODO Refactor + validate csv files
class RebrickableLoader extends BaseLoader
@ -14,11 +16,17 @@ class RebrickableLoader extends BaseLoader
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()

View File

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

View File

@ -3,19 +3,46 @@
namespace AppBundle\Service;
use AppBundle\Entity\LDraw\Model;
use AppBundle\Repository\LDraw\ModelRepository;
use Doctrine\ORM\EntityManagerInterface;
class ModelService
{
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
*
* @return array
*/
public function getAllSubparts(Model $model)
public function getSubmodels(Model $model)
{
foreach ($model->getSubparts() as $subpart) {
$this->resursiveLoadModels($subpart->getSubpart(), $subpart->getCount());
@ -24,6 +51,28 @@ class ModelService
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)
{
if (($model->getSubparts()->count() !== 0)) {

View File

@ -4,22 +4,86 @@ namespace AppBundle\Service;
use AppBundle\Entity\LDraw\Model;
use AppBundle\Entity\Rebrickable\Inventory_Part;
use AppBundle\Entity\Rebrickable\Inventory_Set;
use AppBundle\Entity\Rebrickable\Part;
use AppBundle\Entity\Rebrickable\Set;
use AppBundle\Repository\Rebrickable\Inventory_PartRepository;
use AppBundle\Repository\Rebrickable\Inventory_SetRepository;
use AppBundle\Repository\Rebrickable\SetRepository;
use Doctrine\ORM\EntityManagerInterface;
class SetService
{
/** @var SetRepository */
private $setRepository;
/** @var Inventory_PartRepository */
private $inventoryPartRepository;
/** @var Inventory_SetRepository */
private $inventorySetRepository;
/**
* SetService constructor.
*
* @param Inventory_PartRepository $inventoryPartRepository
* @param EntityManagerInterface $em
*/
public function __construct(Inventory_PartRepository $inventoryPartRepository)
public function __construct(EntityManagerInterface $em)
{
$this->inventoryPartRepository = $inventoryPartRepository;
$this->setRepository = $em->getRepository(Set::class);
$this->inventoryPartRepository = $em->getRepository(Inventory_Part::class);
$this->inventorySetRepository = $em->getRepository(Inventory_Set::class);
}
/**
* Get all sets in the set inventory.
*
* @param Set $set
*
* @return array|null
*/
public function getAllSubSets(Set $set)
{
return $this->inventorySetRepository->findAllBySetNumber($set->getId());
}
/**
* Get all sets in which the model appears.
*
* @param Model $model
*
* @return array
*/
public function getAllByModel(Model $model)
{
return $this->setRepository->findAllByModel($model);
}
/**
* Get all sets in which the model appears.
*
* @param Part $part
*
* @return array
*/
public function getAllByPart(Part $part)
{
return $this->setRepository->findAllByPart($part);
}
/**
* Get total count of sets in database.
*
* @return int
*/
public function getTotalCount()
{
return $this->setRepository->count();
}
public function getPartCount(Set $set, $spare = null, $model = null)
{
return $this->inventoryPartRepository->getPartCount($set, $spare, $model);
}
/**

View File

@ -39,7 +39,7 @@ class StlConverterService
* @param FilesystemInterface $mediaFilesystem Filesystem for generated web assets
* @param StlFixerService $stlFixer
*/
public function __construct($ldview, $mediaFilesystem, $stlFixer)
public function __construct($ldview, FilesystemInterface $mediaFilesystem, StlFixerService $stlFixer)
{
$this->ldview = $ldview;
$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;
}

View File

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

View File

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

View File

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