mirror of
https://github.com/ToxicCrack/PrintABrick.git
synced 2025-05-16 20:30:09 -07:00
Merged branch enhance/improve-loader into dev
This commit is contained in:
commit
9eb99a32ea
1
.gitignore
vendored
1
.gitignore
vendored
@ -18,4 +18,5 @@
|
|||||||
/node_modules/
|
/node_modules/
|
||||||
/app/Resources/libs/semantic/dist
|
/app/Resources/libs/semantic/dist
|
||||||
/web/resources/
|
/web/resources/
|
||||||
|
/web/media/
|
||||||
.php_cs.cache
|
.php_cs.cache
|
@ -29,7 +29,8 @@ For full requirements see Symfony 3.2 [docs](http://symfony.com/doc/3.2/referenc
|
|||||||
|
|
||||||
#### Database
|
#### Database
|
||||||
1. Set application parameters in *app/config/parameters.yml*
|
1. Set application parameters in *app/config/parameters.yml*
|
||||||
2. Generate empty database by running command `$ php bin/console doctrine:database:create`
|
2. Generate empty database by running command `$ php bin/console doctrine:database:create`
|
||||||
3. Load LDraw models into database by running commad `$ php bin/console app:load:ldraw [ldraw_dir_path]`
|
3. Create database tables by running command `$ bin/console doctrine:schema:create`
|
||||||
|
3. Load LDraw models into database by running commad `$ php bin/console app:load:models <ldraw_dir> [--all] [--file=FILE] [--update]`
|
||||||
4. Load Rebrickable data into database by running command `$ php bin/console app:load:rebrickable`
|
4. Load Rebrickable data into database by running command `$ php bin/console app:load:rebrickable`
|
||||||
5. Load relations between LDraw models and Rebrickable parts by running command `$ php bin/console app:load:relation`
|
5. Load relations between LDraw models and Rebrickable parts by running command `$ php bin/console app:load:relation`
|
@ -20,6 +20,7 @@ class AppKernel extends Kernel
|
|||||||
new Oneup\FlysystemBundle\OneupFlysystemBundle(),
|
new Oneup\FlysystemBundle\OneupFlysystemBundle(),
|
||||||
new Knp\Bundle\PaginatorBundle\KnpPaginatorBundle(),
|
new Knp\Bundle\PaginatorBundle\KnpPaginatorBundle(),
|
||||||
new Lexik\Bundle\FormFilterBundle\LexikFormFilterBundle(),
|
new Lexik\Bundle\FormFilterBundle\LexikFormFilterBundle(),
|
||||||
|
new Liip\ImagineBundle\LiipImagineBundle(),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
|
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
|
||||||
|
BIN
app/Resources/assets/images/brickset_logo.png
Normal file
BIN
app/Resources/assets/images/brickset_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
BIN
app/Resources/assets/images/rebrickable_logo.png
Normal file
BIN
app/Resources/assets/images/rebrickable_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
@ -1,85 +1,277 @@
|
|||||||
ModelViewer = function() {
|
var ModelViewer = function($dom_element, model_url) {
|
||||||
var container;
|
var $this = this;
|
||||||
var camera, cameraTarget, scene, renderer, controls, object;
|
this.container = document.createElement('div');
|
||||||
var width, height;
|
this.container.setAttribute('class','model-view');
|
||||||
|
this.dom_element = $dom_element;
|
||||||
|
$dom_element.append(this.container);
|
||||||
|
|
||||||
this.initScene = function($container) {
|
this.camera = null;
|
||||||
width = parseFloat($container.width());
|
this.scene = null;
|
||||||
height = parseFloat($container.height());
|
this.renderer = null;
|
||||||
|
this.controls = null;
|
||||||
|
this.width = parseFloat($dom_element.width());
|
||||||
|
this.height = parseFloat($dom_element.height());
|
||||||
|
this.scale = 1;
|
||||||
|
this.wireframe = false;
|
||||||
|
this.rendering = false;
|
||||||
|
this.container.style.display = "none";
|
||||||
|
this.toggleButton = null;
|
||||||
|
this.background = 0xffffff;
|
||||||
|
this.model_url = model_url;
|
||||||
|
this.loaded = false;
|
||||||
|
|
||||||
camera = new THREE.PerspectiveCamera(45, width/height, 0.1, 1000);
|
this.object = null;
|
||||||
camera.position.set(-2, 2, 0.8);
|
|
||||||
camera.lookAt(new THREE.Vector3(0, 3, 0));
|
|
||||||
|
|
||||||
scene = new THREE.Scene();
|
this.initHtml();
|
||||||
scene.fog = new THREE.FogExp2(0x000000, 0.001);
|
this.initScene();
|
||||||
|
|
||||||
// var grid = new THREE.GridHelper( 30, 70 );
|
|
||||||
// // grid.position.set(30/70,-0.5,30/70);
|
|
||||||
// scene.add( grid );
|
|
||||||
|
|
||||||
// Lights
|
|
||||||
|
|
||||||
light = new THREE.DirectionalLight( 0xffffff );
|
|
||||||
light.position.set( 1, 1, 1 );
|
|
||||||
scene.add( light );
|
|
||||||
|
|
||||||
light = new THREE.DirectionalLight( 0x002288 );
|
|
||||||
light.position.set( -1, -1, -1 );
|
|
||||||
scene.add( light );
|
|
||||||
|
|
||||||
|
|
||||||
scene.add( new THREE.AmbientLight( 0xf0f0f0 ));
|
// this.stats = new Stats();
|
||||||
scene.background = new THREE.Color( 0x000000 );
|
// this.stats.dom.style.position = 'absolute';
|
||||||
|
// this.container.append(this.stats.dom);
|
||||||
|
|
||||||
// renderer
|
|
||||||
renderer = new THREE.WebGLRenderer();
|
|
||||||
renderer.setClearColor( scene.fog.color );
|
|
||||||
renderer.setPixelRatio( window.devicePixelRatio );
|
|
||||||
renderer.setSize( width, height );
|
|
||||||
renderer.gammaInput = true;
|
|
||||||
renderer.gammaOutput = true;
|
|
||||||
renderer.shadowMap.enabled = true;
|
|
||||||
renderer.shadowMap.renderReverseSided = false;
|
|
||||||
|
|
||||||
$container.append(renderer.domElement);
|
function renderLoop() {
|
||||||
|
requestAnimationFrame(renderLoop);
|
||||||
|
if($this.rendering) {
|
||||||
|
if(!$this.loaded) {
|
||||||
|
$this.loadStl($this.model_url);
|
||||||
|
$this.loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
controls = new THREE.OrbitControls( camera, renderer.domElement );
|
if($this.stats) {
|
||||||
controls.addEventListener( 'change', this.render ); // add this only if there is no animation loop (requestAnimationFrame)
|
$this.stats.update();
|
||||||
// controls.enableDamping = true;
|
}
|
||||||
// controls.dampingFactor = 0.25;
|
$this.render();
|
||||||
controls.enableZoom = true;
|
}
|
||||||
};
|
|
||||||
|
$this.resize(parseInt($this.dom_element.width()), parseInt($this.dom_element.height()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
renderLoop();
|
||||||
|
};
|
||||||
|
|
||||||
|
ModelViewer.prototype.initHtml = function () {
|
||||||
|
$this = this;
|
||||||
|
|
||||||
|
var buttons = document.createElement("div");
|
||||||
|
buttons.setAttribute("class", "modelviewer-buttons");
|
||||||
|
|
||||||
|
this.wireframeButton = $('<button/>', {
|
||||||
|
'class':'model',
|
||||||
|
'style':'display:none',
|
||||||
|
'html':'<i class="eye icon"/>Wireframe',
|
||||||
|
'click': $this.toggleMaterial.bind($this)
|
||||||
|
}).appendTo(buttons);
|
||||||
|
|
||||||
|
this.toggleButton = $('<button/>', {
|
||||||
|
'class':'toggle',
|
||||||
|
'html':'<i class="cube icon"/>3D',
|
||||||
|
'click': $this.toggleRendering.bind($this)
|
||||||
|
}).appendTo(buttons);
|
||||||
|
|
||||||
|
this.dom_element.append(buttons);
|
||||||
|
};
|
||||||
|
|
||||||
|
ModelViewer.prototype.initCamera = function () {
|
||||||
|
this.camera = new THREE.PerspectiveCamera(45, this.width / this.height, .1, 300);
|
||||||
|
this.camera.position.z = 80;
|
||||||
|
this.camera.position.y = -45;
|
||||||
|
this.camera.position.x = 35;
|
||||||
|
this.camera.up = new THREE.Vector3(0, 0, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
ModelViewer.prototype.initScene = function() {
|
||||||
|
this.scene = new THREE.Scene();
|
||||||
|
this.scene.background = new THREE.Color( this.background );
|
||||||
|
|
||||||
|
this.scene.fog = new THREE.FogExp2(this.background, 0.06);
|
||||||
|
|
||||||
|
this.initLights();
|
||||||
|
this.initCamera();
|
||||||
|
|
||||||
|
var groundPlaneMaterial = new THREE.MeshPhongMaterial({
|
||||||
|
color: 0xFFFFFF,
|
||||||
|
wireframe: false,
|
||||||
|
transparent: true,
|
||||||
|
opacity: 0.25,
|
||||||
|
fog: false,
|
||||||
|
specular: 0x999999,
|
||||||
|
shininess: 100
|
||||||
|
});
|
||||||
|
|
||||||
|
this.plane = new THREE.Mesh(new THREE.PlaneGeometry(80,80), groundPlaneMaterial);
|
||||||
|
this.plane.receiveShadow = true;
|
||||||
|
this.scene.add(this.plane);
|
||||||
|
|
||||||
|
this.grid = new THREE.GridHelper( 80, 100, 0x000000, 0xAAAAAA);
|
||||||
|
this.grid.rotation.x = Math.PI/2;
|
||||||
|
this.scene.add(this.grid);
|
||||||
|
|
||||||
|
this.renderer = new THREE.WebGLRenderer();
|
||||||
|
this.renderer.setSize(this.width, this.height);
|
||||||
|
this.renderer.setPixelRatio(window.devicePixelRatio ? window.devicePixelRatio : 1);
|
||||||
|
|
||||||
|
this.container.append(this.renderer.domElement);
|
||||||
|
|
||||||
|
this.controls = new THREE.OrbitControls( this.camera, this.renderer.domElement );
|
||||||
|
this.controls.enableZoom = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
ModelViewer.prototype.initLights = function () {
|
||||||
|
this.spotLight = new THREE.SpotLight(0xffffff, 0.8, 0);
|
||||||
|
this.spotLight.position.set(-100, 100, 100);
|
||||||
|
this.spotLight.castShadow = false;
|
||||||
|
this.scene.add(this.spotLight);
|
||||||
|
|
||||||
|
this.bottomSpotLight = new THREE.SpotLight(0xffffff, 0.8, 0);
|
||||||
|
this.bottomSpotLight.position.set(0, -10, -100);
|
||||||
|
this.bottomSpotLight.castShadow = false;
|
||||||
|
this.scene.add(this.bottomSpotLight);
|
||||||
|
|
||||||
|
this.ambientLight = new THREE.AmbientLight(0xffffff, 0.1);
|
||||||
|
this.scene.add(this.ambientLight);
|
||||||
|
|
||||||
|
this.pointLight = new THREE.PointLight(0xfdfdfd, 1, 0);
|
||||||
|
this.pointLight.position.set(32, -39, 35);
|
||||||
|
this.pointLight.castShadow = true;
|
||||||
|
this.scene.add(this.pointLight);
|
||||||
|
};
|
||||||
|
|
||||||
|
ModelViewer.prototype.addModel = function(geometry) {
|
||||||
|
var material = new THREE.MeshPhongMaterial({
|
||||||
|
color: 0x136fc3,
|
||||||
|
specular: 0x0D0D0D,
|
||||||
|
shading: THREE.SmoothShading,
|
||||||
|
shininess: 30,
|
||||||
|
fog: false,
|
||||||
|
side: THREE.DoubleSide,
|
||||||
|
wireframe: this.wireframe,
|
||||||
|
});
|
||||||
|
|
||||||
|
geometry.center();
|
||||||
|
var mesh = new THREE.Mesh(geometry, material);
|
||||||
|
|
||||||
|
mesh.scale.set(this.scale, this.scale, this.scale);
|
||||||
|
|
||||||
|
mesh.geometry.computeFaceNormals();
|
||||||
|
mesh.geometry.computeVertexNormals();
|
||||||
|
mesh.rotation.set(-Math.PI/2,0, 0);
|
||||||
|
mesh.geometry.computeBoundingBox();
|
||||||
|
|
||||||
|
mesh.castShadow = true;
|
||||||
|
// mesh.receiveShadow = true;
|
||||||
|
|
||||||
|
var dims = mesh.geometry.boundingBox.max.clone().sub(mesh.geometry.boundingBox.min);
|
||||||
|
|
||||||
|
maxDim = Math.max(Math.max(dims.x, dims.y), dims.z);
|
||||||
|
|
||||||
|
mesh.position.x = -(mesh.geometry.boundingBox.min.x + mesh.geometry.boundingBox.max.x) / 2 * this.scale;
|
||||||
|
mesh.position.z = -(mesh.geometry.boundingBox.min.y + mesh.geometry.boundingBox.max.y) / 2 * this.scale;
|
||||||
|
mesh.position.y = -mesh.geometry.boundingBox.min.z * this.scale;
|
||||||
|
|
||||||
|
var positionY = (mesh.geometry.boundingBox.max.z + mesh.geometry.boundingBox.min.z)/2 * this.scale;
|
||||||
|
var positionZ = (mesh.geometry.boundingBox.max.y - mesh.geometry.boundingBox.min.y)/2 * this.scale;
|
||||||
|
|
||||||
|
mesh.position.set(0, positionY, positionZ);
|
||||||
|
|
||||||
|
this.object = mesh;
|
||||||
|
|
||||||
|
this.scene.add(mesh);
|
||||||
|
|
||||||
|
this.centerCamera(mesh);
|
||||||
|
};
|
||||||
|
|
||||||
|
ModelViewer.prototype.loadStl = function(model) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var loader = new THREE.STLLoader();
|
||||||
|
|
||||||
this.loadStl = function(model) {
|
|
||||||
var loader = new THREE.STLLoader();
|
|
||||||
loader.load(model, function (geometry) {
|
loader.load(model, function (geometry) {
|
||||||
var material = new THREE.MeshPhongMaterial({color: 0xaaaaaa, shininess:200, specular: 0x333333, shading: THREE.FlatShading});
|
self.addModel(geometry);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
var mesh = new THREE.Mesh(geometry, material);
|
ModelViewer.prototype.centerCamera = function(mesh) {
|
||||||
|
|
||||||
mesh.geometry.computeBoundingBox();
|
var boxHelper = new THREE.BoxHelper( mesh );
|
||||||
var positionY = (mesh.geometry.boundingBox.max.y + mesh.geometry.boundingBox.min.y)/2;
|
|
||||||
|
|
||||||
// mesh.position.set(0, positionY, 0);
|
var sceneCenter = this.objectCenter(mesh);
|
||||||
mesh.rotation.set(Math.PI, 0, 0);
|
|
||||||
mesh.castShadow = true;
|
|
||||||
mesh.receiveShadow = true;
|
|
||||||
scene.add(mesh);
|
|
||||||
|
|
||||||
renderer.render(scene, camera);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.animate = function() {
|
var geometry = mesh.geometry;
|
||||||
|
|
||||||
requestAnimationFrame( this.animate );
|
|
||||||
this.render();
|
|
||||||
};
|
|
||||||
|
|
||||||
this.render = function() {
|
var distanceX = ((geometry.boundingBox.max.x - geometry.boundingBox.min.x) / 2) / Math.tan(this.camera.fov * this.camera.aspect * Math.PI / 360);
|
||||||
|
var distanceY = (geometry.boundingBox.max.y - geometry.boundingBox.min.y) / 2 / Math.tan(this.camera.fov * this.camera.aspect * Math.PI / 360);
|
||||||
|
var distanceZ = (geometry.boundingBox.max.z - geometry.boundingBox.min.z) / 2 / Math.tan(this.camera.fov * Math.PI / 360);
|
||||||
|
|
||||||
renderer.render(scene, camera);
|
var maxDistance = Math.max(Math.max(distanceX, distanceY), distanceZ);
|
||||||
|
maxDistance *= 1.9 * this.scale;
|
||||||
|
|
||||||
};
|
var cameraPosition = this.camera.position.normalize().multiplyScalar(maxDistance);
|
||||||
|
|
||||||
|
this.controls.maxDistance = 3 * maxDistance;
|
||||||
|
|
||||||
|
this.controls.position0 = cameraPosition;
|
||||||
|
this.controls.target0 = sceneCenter;
|
||||||
|
this.controls.reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
ModelViewer.prototype.toggleRendering = function () {
|
||||||
|
if($this.rendering) {
|
||||||
|
$this.container.style.display = "none";
|
||||||
|
$this.rendering = false;
|
||||||
|
$this.toggleButton.html('<i class="cube icon"/>3D');
|
||||||
|
$this.wireframeButton.hide();
|
||||||
|
} else {
|
||||||
|
$this.container.style.display = "block";
|
||||||
|
$this.rendering = true;
|
||||||
|
$this.toggleButton.html('<i class="close icon"/>Close');
|
||||||
|
$this.wireframeButton.show();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ModelViewer.prototype.toggleMaterial = function () {
|
||||||
|
if($this.wireframe) {
|
||||||
|
$this.wireframe = false;
|
||||||
|
$this.wireframeButton.html('<i class="eye icon"/>Wireframe')
|
||||||
|
} else {
|
||||||
|
$this.wireframe = true;
|
||||||
|
$this.wireframeButton.html('<i class="eye icon"/>Solid')
|
||||||
|
}
|
||||||
|
|
||||||
|
this.scene.traverse(function(object) {
|
||||||
|
if (object instanceof THREE.Mesh) {
|
||||||
|
object.material.wireframe = $this.wireframe;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
ModelViewer.prototype.objectCenter = function (mesh) {
|
||||||
|
var middle = new THREE.Vector3();
|
||||||
|
var geometry = mesh.geometry;
|
||||||
|
|
||||||
|
geometry.center();
|
||||||
|
geometry.computeBoundingBox();
|
||||||
|
|
||||||
|
middle.x = (geometry.boundingBox.max.x + geometry.boundingBox.min.x) / 2;
|
||||||
|
middle.y = (geometry.boundingBox.max.y + geometry.boundingBox.min.y) / 2;
|
||||||
|
middle.z = (geometry.boundingBox.max.z + geometry.boundingBox.min.z) / 2;
|
||||||
|
|
||||||
|
mesh.localToWorld(middle);
|
||||||
|
return middle;
|
||||||
|
};
|
||||||
|
|
||||||
|
ModelViewer.prototype.resize = function(width, height) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.camera.aspect = width / height;
|
||||||
|
this.camera.updateProjectionMatrix();
|
||||||
|
this.renderer.setSize(width, height);
|
||||||
|
};
|
||||||
|
|
||||||
|
ModelViewer.prototype.render = function() {
|
||||||
|
this.renderer.render(this.scene, this.camera);
|
||||||
};
|
};
|
@ -2,4 +2,27 @@ $(document).ready(function () {
|
|||||||
$('.ui.dropdown')
|
$('.ui.dropdown')
|
||||||
.dropdown()
|
.dropdown()
|
||||||
;
|
;
|
||||||
|
|
||||||
|
$('.image.load img')
|
||||||
|
.visibility({
|
||||||
|
type : 'image',
|
||||||
|
transition : 'fade in',
|
||||||
|
duration : 1000
|
||||||
|
})
|
||||||
|
;
|
||||||
|
|
||||||
|
$('.ui.rating')
|
||||||
|
.rating("disable")
|
||||||
|
;
|
||||||
|
|
||||||
|
$('.tabular.menu .item').tab();
|
||||||
|
|
||||||
|
$('.message .close')
|
||||||
|
.on('click', function() {
|
||||||
|
$(this)
|
||||||
|
.closest('.message')
|
||||||
|
.transition('fade')
|
||||||
|
;
|
||||||
|
})
|
||||||
|
;
|
||||||
});
|
});
|
@ -1,3 +1,43 @@
|
|||||||
.ui.fixed + .ui.main {
|
.default-theme {
|
||||||
margin-top: 5em;
|
|
||||||
|
.ui.fixed + .ui.grid {
|
||||||
|
border-radius: 0;
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-info {
|
||||||
|
min-height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.fixed + .ui.main {
|
||||||
|
margin-top: 3em;
|
||||||
|
padding-bottom: 4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
padding-left: 30px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link:before {
|
||||||
|
width: 23px;
|
||||||
|
height: 23px;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link.brickset:before {
|
||||||
|
content: '';
|
||||||
|
background: url("/resources/images/brickset_logo.png");
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link.rebrickable:before {
|
||||||
|
content: '';
|
||||||
|
background: url("/resources/images/rebrickable_logo.png");
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
34
app/Resources/assets/style/modelviewer.scss
Normal file
34
app/Resources/assets/style/modelviewer.scss
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
.model-container {
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
border: 1px solid #DDDDDD;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modelviewer-buttons {
|
||||||
|
text-align: right;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
height: 35px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 3px 4px;
|
||||||
|
|
||||||
|
> button {
|
||||||
|
border: none;
|
||||||
|
height: 100%;
|
||||||
|
margin-left: 5px;
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-view {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
@import "variables";
|
@import "variables";
|
||||||
|
|
||||||
@import "main";
|
@import "main";
|
||||||
|
@import "modelviewer";
|
||||||
|
@ -46,6 +46,8 @@
|
|||||||
4168950: 3815c01
|
4168950: 3815c01
|
||||||
73418: 3815c01
|
73418: 3815c01
|
||||||
|
|
||||||
|
82359: 3626b
|
||||||
|
|
||||||
122c02: 122c01
|
122c02: 122c01
|
||||||
|
|
||||||
# Bucket 1 x 1 x 1 Cylindrical
|
# Bucket 1 x 1 x 1 Cylindrical
|
||||||
@ -119,6 +121,22 @@ u9147p01c06: u9147p01c02
|
|||||||
u9147p02c02: u9147p01c02
|
u9147p02c02: u9147p01c02
|
||||||
u9147p03c02: u9147p01c02
|
u9147p03c02: u9147p01c02
|
||||||
|
|
||||||
|
# Figure Fabuland Monkey
|
||||||
|
u595p01c08: u595p01c04
|
||||||
|
u595p01c07: u595p01c04
|
||||||
|
u595p01c06: u595p01c04
|
||||||
|
u595p01c05: u595p01c04
|
||||||
|
|
||||||
|
# Figure Fabuland Monkey Head
|
||||||
|
u595p02c03: u595p02c02
|
||||||
|
|
||||||
|
# Figure Fabuland Monkey 2
|
||||||
|
u595p02c05: u595p02c04
|
||||||
|
|
||||||
|
# Figure Fabuland Mouse 1
|
||||||
|
u9105p01c06: u9105p01c02
|
||||||
|
u9105p01c03: u9105p01c02
|
||||||
|
|
||||||
# Figure Fabuland Elephant Head
|
# Figure Fabuland Elephant Head
|
||||||
u588p02c02: u588p01c02
|
u588p02c02: u588p01c02
|
||||||
|
|
||||||
@ -164,4 +182,39 @@ u588p02c02: u588p01c02
|
|||||||
|
|
||||||
# Hinge Control Stick and Base
|
# Hinge Control Stick and Base
|
||||||
73587: 4592c01
|
73587: 4592c01
|
||||||
4296152: 4592c01
|
4296152: 4592c01
|
||||||
|
|
||||||
|
4505: 4505a
|
||||||
|
6093: 6093a
|
||||||
|
|
||||||
|
90462a: 90462
|
||||||
|
|
||||||
|
# Minifig Mechanical SW Battle Droid
|
||||||
|
30375cs1: 30375cs0
|
||||||
|
30375cs2: 30375cs0
|
||||||
|
30375cs3: 30375cs0
|
||||||
|
|
||||||
|
2958c01: 2723
|
||||||
|
|
||||||
|
32181c03: 32181c01
|
||||||
|
|
||||||
|
76019: 76244
|
||||||
|
4107539: 76244
|
||||||
|
|
||||||
|
3680c02: 3680c01
|
||||||
|
4221774: 3680c01
|
||||||
|
9245: 3680c01
|
||||||
|
9246: 3680c01
|
||||||
|
9258: 3680c01
|
||||||
|
9328: 3680c01
|
||||||
|
9352: 3680c01
|
||||||
|
|
||||||
|
4508c01: 251c01
|
||||||
|
|
||||||
|
4100338: 2557c01
|
||||||
|
4100340: 6051c01
|
||||||
|
|
||||||
|
4100339: 2559c01
|
||||||
|
75192: 2977c01
|
||||||
|
|
||||||
|
4539364: 64776
|
@ -89,7 +89,6 @@
|
|||||||
10119: 51704
|
10119: 51704
|
||||||
3149: 3149d
|
3149: 3149d
|
||||||
75998: 4493c00
|
75998: 4493c00
|
||||||
10119: 51704
|
|
||||||
30658: 3404
|
30658: 3404
|
||||||
|
|
||||||
59275: 2599
|
59275: 2599
|
||||||
@ -153,4 +152,59 @@ wheel2a: 568c01
|
|||||||
11895pr0001c01: 11895
|
11895pr0001c01: 11895
|
||||||
92456pr0021c01: 92241p03c01
|
92456pr0021c01: 92241p03c01
|
||||||
|
|
||||||
15672: 92946
|
15672: 92946
|
||||||
|
|
||||||
|
3614a: 3614
|
||||||
|
3614b: 3614
|
||||||
|
|
||||||
|
75215: 4694c01
|
||||||
|
|
||||||
|
6093: 6093a
|
||||||
|
|
||||||
|
3626bpr0895: 82359
|
||||||
|
|
||||||
|
6272c01: 6272
|
||||||
|
|
||||||
|
76320: 32181c02
|
||||||
|
|
||||||
|
95292c01: 75348
|
||||||
|
2909c03: 75348
|
||||||
|
2909c02: 75348
|
||||||
|
|
||||||
|
# Technic figures
|
||||||
|
tech001: 2698c01
|
||||||
|
tech002: 2698c01
|
||||||
|
tech003: 2698c01
|
||||||
|
tech004: 2698c01
|
||||||
|
tech005: 2698c01
|
||||||
|
tech006: 2698c01
|
||||||
|
tech007: 2698c01
|
||||||
|
tech008: 2698c01
|
||||||
|
tech009: 2698c01
|
||||||
|
tech010: 2698c01
|
||||||
|
tech011: 2698c01
|
||||||
|
tech011a: 2698c01
|
||||||
|
tech012: 2698c01
|
||||||
|
tech013: 2698c01
|
||||||
|
tech014: 2698c01
|
||||||
|
tech014a: 2698c01
|
||||||
|
tech015: 2698c01
|
||||||
|
tech016: 2698c01
|
||||||
|
tech016a: 2698c01
|
||||||
|
tech017: 2698c01
|
||||||
|
tech017a: 2698c01
|
||||||
|
tech018: 2698c01
|
||||||
|
tech019: 2698c01
|
||||||
|
tech020: 2698c01
|
||||||
|
tech021: 2698c01
|
||||||
|
tech022: 2698c01
|
||||||
|
tech023: 2698c01
|
||||||
|
tech024: 2698c01
|
||||||
|
tech025: 2698c01
|
||||||
|
tech026: 2698c01
|
||||||
|
tech027: 2698c01
|
||||||
|
tech028: 2698c01
|
||||||
|
tech029: 2698c01
|
||||||
|
|
||||||
|
33299a: 33299
|
||||||
|
33299b: 33299
|
@ -1,40 +1,48 @@
|
|||||||
|
{% extends 'html.html.twig' %}
|
||||||
|
|
||||||
{% import 'macros/elements.html.twig' as elements %}
|
{% import 'macros/elements.html.twig' as elements %}
|
||||||
|
|
||||||
<!DOCTYPE html>
|
{% block body %}
|
||||||
<html>
|
<div class="ui fixed inverted menu">
|
||||||
<head>
|
{{ knp_menu_render('mainMenu') }}
|
||||||
<meta charset="UTF-8" />
|
</div>
|
||||||
<title>{% block title %}Welcome!{% endblock %}</title>
|
{% block page %}
|
||||||
{% block stylesheets %}
|
<div class="ui main">
|
||||||
<link rel="stylesheet" href="{{ asset('resources/css/main.css') }}">
|
<div class="ui container">
|
||||||
{% endblock %}
|
<div class="ui masthead vertical segment">
|
||||||
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
|
<div class="introduction">
|
||||||
</head>
|
<div class="ui small breadcrumb">
|
||||||
<body>
|
{% for breadcrumb_item in knp_menu_get_breadcrumbs_array(knp_menu_get_current_item('mainMenu')) %}
|
||||||
{% block body %}
|
{% if not loop.last %}
|
||||||
<div class="ui fixed inverted menu">
|
<a class="section" href="{{ breadcrumb_item.uri }}">{{ breadcrumb_item.label }}</a>
|
||||||
{{ knp_menu_render('mainMenu') }}
|
<i class="right chevron icon divider"></i>
|
||||||
|
{% else %}
|
||||||
|
<a class="active section">{{ breadcrumb_item.label }}</a>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<h1 class="ui header">{% block header %}{% endblock %}</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui vertical segment content">
|
||||||
|
{% for label, flashes in app.session.flashbag.all %}
|
||||||
|
{% for flash in flashes %}
|
||||||
|
{{ elements.flash(label,flash) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui main container">
|
</div>
|
||||||
{% for label, flashes in app.session.flashbag.all %}
|
{% endblock page %}
|
||||||
{% for flash in flashes %}
|
<div class="ui black inverted vertical footer segment stripe">
|
||||||
{{ elements.flash(label,flash) }}
|
{% block footer %}
|
||||||
{% endfor %}
|
<div class="ui center aligned container">
|
||||||
{% endfor %}
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
</div>
|
||||||
{% block javascripts %}
|
{% endblock %}
|
||||||
|
|
||||||
<script type="text/javascript" src="{{ asset('resources/js/three.js') }}"></script>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="{{ asset('resources/js/OrbitControls.js') }}"></script>
|
|
||||||
|
|
||||||
|
|
||||||
<script src="{{ asset('resources/js/main.js') }}"></script>
|
|
||||||
{% endblock %}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -14,12 +14,14 @@
|
|||||||
</div>
|
</div>
|
||||||
{{ form_end(form) }}
|
{{ form_end(form) }}
|
||||||
|
|
||||||
|
<h3>{{ sets|length }}</h3>
|
||||||
|
|
||||||
<div class="ui seven column grid">
|
<div class="ui seven column grid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for set in sets %}
|
{% for set in sets %}
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<a href="{{ url('set_detail', {'number': set.number~'-'~set.numberVariant, 'name' : set.name|escape('url') }) }}">
|
<a href="{{ url('set_detail', {'number': set.number~'-'~set.numberVariant, 'name' : set.name|escape('url') }) }}">
|
||||||
<img style="width: 100%" src="{{ set.largeThumbnailURL }}">
|
<img style="width: 100%" src="{{ set.legoSetID|setImage|imagine_filter('rebrickable_set_min') }}">
|
||||||
<p>{{ set.LegoSetID }} - {{ set.name }}</p>
|
<p>{{ set.LegoSetID }} - {{ set.name }}</p>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
9
app/Resources/views/brickset/images.html.twig
Normal file
9
app/Resources/views/brickset/images.html.twig
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<div class="ui six doubling cards">
|
||||||
|
{% for image in images %}
|
||||||
|
<div class="card">
|
||||||
|
<a class="ui bordered fluid image" href="{{ image.imageURL }}" data-lightbox="setImages">
|
||||||
|
<img src="{{ image.thumbnailURL }}">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
30
app/Resources/views/brickset/instructions.html.twig
Normal file
30
app/Resources/views/brickset/instructions.html.twig
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{% import 'macros/utils.html.twig' as utils %}
|
||||||
|
|
||||||
|
{% if instructions|length != 0 %}
|
||||||
|
<p>
|
||||||
|
{{ 'set.instructions.text' | trans }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<table class="ui celled padded table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{{ 'set.instructions.description' | trans }}</th>
|
||||||
|
<th>{{ 'set.instructions.filesize' | trans }}</th>
|
||||||
|
<th>{{ 'set.instructions.filename' | trans }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for instruction in instructions %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ instruction.description }}</td>
|
||||||
|
<td>{{ utils.bytesToSize( remoteSize(instruction.uRL)) }}</td>
|
||||||
|
<td><a href="{{ instruction.uRL }}">{{ remoteFilename(instruction.uRL) }}</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% else %}
|
||||||
|
<h2 class="ui center aligned icon">
|
||||||
|
<i class="circular warning icon"></i>
|
||||||
|
</h2>
|
||||||
|
{% endif %}
|
26
app/Resources/views/brickset/reviews.html.twig
Normal file
26
app/Resources/views/brickset/reviews.html.twig
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<div class="ui comments">
|
||||||
|
{% for review in reviews %}
|
||||||
|
<div class="comment">
|
||||||
|
<a class="avatar">
|
||||||
|
{#<img src="/images/avatar/small/matt.jpg">#}
|
||||||
|
</a>
|
||||||
|
<div class="content">
|
||||||
|
<div class="header">
|
||||||
|
<h4>{{ review.title }}</h4>
|
||||||
|
</div>
|
||||||
|
<span class="author">{{ review.author }}</span> {{ review.hTML }}
|
||||||
|
<div class="metadata">
|
||||||
|
<span class="date">{{ review.datePosted|date("Y.m.d H:m:i")}}</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="text">
|
||||||
|
{{ review.review|raw }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Overall rating <div class="ui star rating" data-rating="{{ review.overallRating }}" data-max-rating="5"></div>
|
||||||
|
{#Value for money <div class="ui star rating" data-rating="{{ review.valueForMoney }}" data-max-rating="5"></div>#}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
@ -1,6 +1,14 @@
|
|||||||
{% extends 'base.html.twig' %}
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
{% block content %}
|
{% block page %}
|
||||||
|
<div class="ui grid massive message vertical">
|
||||||
|
<div class="ui container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="h1 ui huge header">
|
||||||
|
Hello, world!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
{% block title %}{{ 'page.error.title'|trans }}{% endblock %}
|
{% block title %}{{ 'page.error.title'|trans }}{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2 class="ui center aligned icon header">
|
<h1 class="ui center aligned icon header">
|
||||||
<i class="circular warning icon"></i>
|
<i class="circular warning icon"></i>
|
||||||
{{ 'page.error.large'|trans }}
|
{{ 'page.error.large'|trans }}
|
||||||
</h2>
|
</h1>
|
||||||
<p class="ui center aligned">{{ 'page.error.text'|trans }}</p>
|
<p class="ui center aligned">{{ 'page.error.text'|trans }}</p>
|
||||||
{% endblock %}
|
{% endblock %}
|
25
app/Resources/views/html.html.twig
Normal file
25
app/Resources/views/html.html.twig
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>{% block title %}PrintABrick{% endblock %}</title>
|
||||||
|
{% block stylesheets %}
|
||||||
|
<link rel="stylesheet" href="{{ asset('resources/css/main.css') }}">
|
||||||
|
{% endblock %}
|
||||||
|
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
|
||||||
|
</head>
|
||||||
|
<body class="default-theme">
|
||||||
|
{% block body %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
|
||||||
|
<script type="text/javascript" src="{{ asset('resources/js/three.js') }}"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="{{ asset('resources/js/OrbitControls.js') }}"></script>
|
||||||
|
|
||||||
|
<script src="{{ asset('resources/js/main.js') }}"></script>
|
||||||
|
{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,85 +0,0 @@
|
|||||||
{% extends 'base.html.twig' %}
|
|
||||||
|
|
||||||
{% import 'macros/elements.html.twig' as elements %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
{% if model %}
|
|
||||||
<dl>
|
|
||||||
<dt>number:</dt><dd>{{ model.number }}</dd>
|
|
||||||
<dt>name:</dt><dd>{{ model.name }}</dd>
|
|
||||||
<dt>category:</dt><dd>{{ model.category ? model.category.name }}</dd>
|
|
||||||
<dt>type:</dt><dd>{{ model.type ? model.type.name }}</dd>
|
|
||||||
<dt>model:</dt><dd>{{ model.path }}</dd>
|
|
||||||
<dt>author:</dt><dd>{{ model.author }}</dd>
|
|
||||||
<dt>keywords:</dt>
|
|
||||||
<dd>
|
|
||||||
{% for keyword in model.keywords %}
|
|
||||||
<span class="ui label">{{ keyword.name }}</span>
|
|
||||||
{% endfor %}
|
|
||||||
</dd>
|
|
||||||
<dt>aliases:</dt>
|
|
||||||
<dd>
|
|
||||||
{% for alias in model.aliases %}
|
|
||||||
<span class="ui label">{{ alias.number }}</span>
|
|
||||||
{% endfor %}
|
|
||||||
</dd>
|
|
||||||
<dd>Download:</dd>
|
|
||||||
<dt><a href="{{ path('model_stl', {'number' : model.number })}}">{{ model.number }}</a></dt>
|
|
||||||
<dt>rebrickable parts ({{ rbParts|length }}):</dt>
|
|
||||||
<dd>
|
|
||||||
<p>
|
|
||||||
<div class="ui eight doubling cards">
|
|
||||||
{% for alias in rbParts %}
|
|
||||||
<a href="{{ url('rebrickable_part_show', {number:alias.number}) }}" class="ui label">{{ alias.number }}</a>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</p>
|
|
||||||
</dd>
|
|
||||||
|
|
||||||
</dl>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div style="display: flex; flex-wrap: wrap">
|
|
||||||
<div id="model" style="height: 300px; width: 300px; padding: 5px; display: inline-block"></div>
|
|
||||||
<div style="height: 300px; width: 300px; padding: 5px; display: inline-block">
|
|
||||||
<img src="{{ url('model_image', {'number': model.number}) }}" style="max-height: 90%; max-width: 100%">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h4 class="ui horizontal divider header">
|
|
||||||
<i class="puzzle icon"></i> Subparts of this model
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
{% for subpart in model.subparts %}
|
|
||||||
{{ elements.part(subpart.subpart) }}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<h4 class="ui horizontal divider header">
|
|
||||||
<i class="cube icon"></i> Model is subpart of
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
{% for subpart in model.parents %}
|
|
||||||
{{ elements.part(subpart.parent) }}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<h4 class="ui horizontal divider header">
|
|
||||||
<i class="cubes icon"></i> Sets ({{ sets|length }})
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
{% for set in sets %}
|
|
||||||
<span style="margin: 5px"><a href="{{ url('set_detail', {number:set.number}) }}">{{ set.number }}</a></span>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block javascripts %}
|
|
||||||
{{ parent() }}
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
window.onload = function() {
|
|
||||||
modelView = new ModelViewer();
|
|
||||||
var scene = modelView.initScene($('#model'));
|
|
||||||
modelView.loadStl('{{ path('model_stl', {'number' : model.number })}}');
|
|
||||||
modelView.render();
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
@ -1,7 +1,13 @@
|
|||||||
{% macro part(model) %}
|
{% macro part(model) %}
|
||||||
<div style="height: 100px; width: 100px; padding: 5px; display: inline-block;">
|
<div class="column">
|
||||||
<img src="{{ url('model_image', {'number': model.number }) }}" style="max-height: 90%; max-width: 100%;">
|
<div class="ui bordered fluid image">
|
||||||
<p><a href="{{ url('model_detail', {'number': model.number}) }}">{{ model.number }}</a></p>
|
<a href="{{ url('model_detail', {'number': model.number})}}">
|
||||||
|
<div class="image">
|
||||||
|
<img src="{{ asset('/ldraw/images/'~model.number~'.png') | imagine_filter('model_min') }}" data-src="{{ asset('/ldraw/images/'~model.number~'.png') | imagine_filter('model_min') }}" class="transition visible">
|
||||||
|
</div>
|
||||||
|
<div class="ui bottom attached label {% if model.parts|length == 0 %}black{% endif %}">{{ model.number }}</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
|
21
app/Resources/views/macros/utils.html.twig
Normal file
21
app/Resources/views/macros/utils.html.twig
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{#http://stackoverflow.com/a/15303004#}
|
||||||
|
{% macro bytesToSize(bytes) %}
|
||||||
|
{% spaceless %}
|
||||||
|
{% set kilobyte = 1024 %}
|
||||||
|
{% set megabyte = kilobyte * 1024 %}
|
||||||
|
{% set gigabyte = megabyte * 1024 %}
|
||||||
|
{% set terabyte = gigabyte * 1024 %}
|
||||||
|
|
||||||
|
{% if bytes < kilobyte %}
|
||||||
|
{{ bytes ~ ' B' }}
|
||||||
|
{% elseif bytes < megabyte %}
|
||||||
|
{{ (bytes / kilobyte)|number_format(2, '.') ~ ' KB' }}
|
||||||
|
{% elseif bytes < gigabyte %}
|
||||||
|
{{ (bytes / megabyte)|number_format(2, '.') ~ ' MB' }}
|
||||||
|
{% elseif bytes < terabyte %}
|
||||||
|
{{ (bytes / gigabyte)|number_format(2, '.') ~ ' GB' }}
|
||||||
|
{% else %}
|
||||||
|
{{ (bytes / terabyte)|number_format(2, '.') ~ ' TB' }}
|
||||||
|
{% endif %}
|
||||||
|
{% endspaceless %}
|
||||||
|
{% endmacro %}
|
122
app/Resources/views/model/detail.html.twig
Normal file
122
app/Resources/views/model/detail.html.twig
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
|
{% import 'macros/elements.html.twig' as elements %}
|
||||||
|
|
||||||
|
{% block title %}#{{ model.number }} - {{ model.name }}{% endblock %}
|
||||||
|
|
||||||
|
{% block header %}#{{ model.number }} - {{ model.name }}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="ui grid">
|
||||||
|
<div class="column ten wide">
|
||||||
|
<div id="model-viewer" class="model-container">
|
||||||
|
<img src="{{ asset('ldraw/images/'~model.number~'.png') | imagine_filter('model_large')}}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column six wide">
|
||||||
|
<div class="grey">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>category</th><td>{{ model.category ? model.category.name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>model</th><td>{{ model.path }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>author</th><td>{{ model.author.name }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>keywords:</dt>
|
||||||
|
<dd>
|
||||||
|
{% for keyword in model.keywords %}
|
||||||
|
<span class="ui label">{{ keyword.name }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</dd>
|
||||||
|
<dt>aliases:</dt>
|
||||||
|
<dd>
|
||||||
|
{% for alias in model.aliases %}
|
||||||
|
<span>{{ alias.number }}</span>{% if not loop.last %},{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</dd>
|
||||||
|
<dd>Download:</dd>
|
||||||
|
<dt><a href="{{ url('media_file', {'path': model.path}) }}">{{ model.number }}</a></dt>
|
||||||
|
<dt>rebrickable parts ({{ rbParts|length }}):</dt>
|
||||||
|
<dd>
|
||||||
|
{#<p>#}
|
||||||
|
{#<div class="ui eight doubling cards">#}
|
||||||
|
{#{% for alias in rbParts %}#}
|
||||||
|
{#<a href="{{ url('reb_part_detail', {number:alias.number}) }}" class="ui label">{{ alias.number }}</a>#}
|
||||||
|
{#{% endfor %}#}
|
||||||
|
{#</div>#}
|
||||||
|
{#</p>#}
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<h4 class="ui horizontal divider header">
|
||||||
|
Related Models
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
|
||||||
|
<h5 class="ui horizontal divider header">
|
||||||
|
Subparts of this model
|
||||||
|
</h5>
|
||||||
|
|
||||||
|
<div class="ui eight column grid">
|
||||||
|
{% for subpart in model.subparts %}
|
||||||
|
<div class="column">
|
||||||
|
{{ elements.part(subpart.subpart) }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h5 class="ui horizontal divider header">
|
||||||
|
Model is subpart of
|
||||||
|
</h5>
|
||||||
|
|
||||||
|
<div class="ui eight column grid">
|
||||||
|
{% for subpart in model.parents %}
|
||||||
|
<div class="column">
|
||||||
|
{{ elements.part(subpart.parent) }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h5 class="ui horizontal divider header">
|
||||||
|
Model pairs with
|
||||||
|
</h5>
|
||||||
|
|
||||||
|
<div class="ui eight column grid">
|
||||||
|
{% for subpart in related %}
|
||||||
|
<div class="column">
|
||||||
|
{{ elements.part(subpart) }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h4 class="ui horizontal divider header">
|
||||||
|
<i class="cubes icon"></i> Sets ({{ sets|length }})
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
{% for set in sets %}
|
||||||
|
<span style="margin: 5px"><a href="{{ url('set_detail', {number:set.number}) }}">{{ set.number }}</a></span>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
{{ parent() }}
|
||||||
|
<script type="text/javascript">
|
||||||
|
window.onload = function() {
|
||||||
|
modelView = new ModelViewer($('#model-viewer'), '{{ url('media_file', {'path': model.path }) }}');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
@ -2,8 +2,14 @@
|
|||||||
|
|
||||||
{% import 'macros/elements.html.twig' as elements %}
|
{% import 'macros/elements.html.twig' as elements %}
|
||||||
|
|
||||||
|
{% block title %}{{ 'page.model.index' | trans }}{% endblock %}
|
||||||
|
|
||||||
|
{% block header %}{{ 'page.model.index' | trans }}{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<form method="get" action="." class="ui form">
|
<div class="ui container stackable grid">
|
||||||
|
<div class="column four wide">
|
||||||
|
<form method="get" action="" class="ui form">
|
||||||
{{ form_start(form) }}
|
{{ form_start(form) }}
|
||||||
|
|
||||||
{{ form_row(form.search) }}
|
{{ form_row(form.search) }}
|
||||||
@ -16,18 +22,17 @@
|
|||||||
</div>
|
</div>
|
||||||
{{ form_end(form) }}
|
{{ form_end(form) }}
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="column twelve wide">
|
||||||
|
{{ knp_pagination_render(models) }}
|
||||||
<p>{{ models.getTotalItemCount }}</p>
|
<p>{{ models.getTotalItemCount }}</p>
|
||||||
<div class="ui ten column grid">
|
<div class="ui eight column grid">
|
||||||
<div class="row">
|
{% for model in models %}
|
||||||
{% for model in models %}
|
{{ elements.part(model) }}
|
||||||
<div class="column">
|
{% endfor %}
|
||||||
{{ elements.part(model) }}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{ knp_pagination_render(models) }}
|
{{ knp_pagination_render(models) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<table class="ui celled padded table">
|
<table class="ui celled small padded table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th></th>
|
<th></th>
|
||||||
|
@ -9,28 +9,33 @@
|
|||||||
<dt>category:</dt><dd>{{ part.category ? part.category.name }}</dd>
|
<dt>category:</dt><dd>{{ part.category ? part.category.name }}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<div style="display: flex; flex-wrap: wrap">
|
|
||||||
{% if apiPart is not null %}
|
|
||||||
<div style="height: 300px; width: 300px; padding: 5px; display: inline-block">
|
|
||||||
<img src="{{ apiPart.imgUrl }}" style="max-height: 90%; max-width: 100%">
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div style="height: 300px; width: 300px; padding: 5px; display: inline-block">
|
|
||||||
<img src="{{ url('model_image', {number:part.number}) }}" style="max-height: 90%; max-width: 100%">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% if part.model %}
|
{% if apiPart is not null %}
|
||||||
{{ elements.part(part.model) }}
|
<a href="{{ apiPart.url }}">Rebrickable</a>
|
||||||
{% endif %}
|
|
||||||
</div>
|
<img class="image ui middle" src="{{ apiPart.imgUrl }}" style="max-height: 90%; max-width: 100%">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if part.model %}
|
||||||
|
{{ elements.part(part.model) }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<h4 class="ui horizontal divider header">
|
<h4 class="ui horizontal divider header">
|
||||||
<i class="puzzle icon"></i> Sets
|
<i class="puzzle icon"></i> Sets
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
|
<div class="ui eight column grid">
|
||||||
{% for set in sets %}
|
{% for set in sets %}
|
||||||
<span style="margin: 5px"><a href="{{ url('set_detail', {number:set.number}) }}">{{ set.number }}</a></span>
|
<div class="column">
|
||||||
|
<div class="ui fluid bordered image">
|
||||||
|
<a href="{{ url('set_detail', {number:set.number}) }}">
|
||||||
|
<img class="ui bordered image" src="{{ set.number|setImage|imagine_filter('rebrickable_set_min') }}">
|
||||||
|
<div class="ui bottom attached label">{{ set.number }}<br></div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
<div>
|
||||||
|
|
||||||
{{ dump(apiPart) }}
|
{{ dump(apiPart) }}
|
||||||
|
|
||||||
|
25
app/Resources/views/rebrickable/part/index.html.twig
Normal file
25
app/Resources/views/rebrickable/part/index.html.twig
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="ui seven column grid">
|
||||||
|
<div class="row">
|
||||||
|
{% for part in parts %}
|
||||||
|
<div class="column">
|
||||||
|
<div class="ui fluid bordered image">
|
||||||
|
<a href="{{ path('reb_part_detail', {number: part.number}) }}">
|
||||||
|
<div class="image load">
|
||||||
|
<img src="{{ part.number|partImage(-1)| imagine_filter('rebrickable_part_min') }}" data-src="{{ part.number|partImage(-1)| imagine_filter('rebrickable_part_min') }}" class="transition visible">
|
||||||
|
</div>
|
||||||
|
<div class="ui bottom attached label {{ part.model == null ? 'black' : 'red'}}">{{ part.number }}</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>{{ parts.getTotalItemCount }}</p>
|
||||||
|
|
||||||
|
{{ knp_pagination_render(parts) }}
|
||||||
|
{% endblock %}
|
@ -1,58 +0,0 @@
|
|||||||
{% extends 'base.html.twig' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
{% if set is not null %}
|
|
||||||
<dl>
|
|
||||||
<dt>number:</dt><dd>{{ set.number }}</dd>
|
|
||||||
<dt>year:</dt><dd>{{ set.year }}</dd>
|
|
||||||
<dt>name:</dt><dd>{{ set.name }}</dd>
|
|
||||||
<dt>theme:</dt><dd>{{ set.theme.name }}</dd>
|
|
||||||
<dt>count of parts:</dt><dd>{{ set.partCount }}</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<img class="ui bordered image medium" src="{{ rbset ? rbset.imgUrl }}">
|
|
||||||
|
|
||||||
|
|
||||||
<h4 class="ui horizontal divider header">
|
|
||||||
<i class="cubes icon"></i> Parts {{ inventoryParts|length }}
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
<div class="ui eight column grid">
|
|
||||||
{% for inventoryPart in inventoryParts %}
|
|
||||||
<div class="column">
|
|
||||||
<div class="ui fluid image {{ inventoryPart.part.model == null ? 'active dimmer'}}" style="height: 150px;">
|
|
||||||
<a class="ui right red circular label">{{ inventoryPart.quantity }}</a>
|
|
||||||
<a href="{{ path('rebrickable_part_show', {number: inventoryPart.part.number}) }}">
|
|
||||||
<img src="https://rebrickable.com/media/parts/ldraw/{{inventoryPart.color ? inventoryPart.color.id }}/{{ inventoryPart.part.number }}.png">
|
|
||||||
<div style="border-bottom: #{{ inventoryPart.color.rgb }} 5px solid" class="ui bottom attached label">{{ inventoryPart.part.number }}<br>{{ inventoryPart.isSpare ? 'Spare' : 'Regular' }}</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
<div>
|
|
||||||
|
|
||||||
|
|
||||||
<h4 class="ui horizontal divider header">
|
|
||||||
<i class="cubes icon"></i> Models {{ parts|length }}
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
<div class="ui eight column grid">
|
|
||||||
{% for part in parts %}
|
|
||||||
<div class="column">
|
|
||||||
<div class="ui bordered fluid image">
|
|
||||||
<a href="{{ path('model_detail', {number: part.number}) }}">
|
|
||||||
<img src="https://rebrickable.com/media/parts/ldraw/-1/{{ part.number }}.png">
|
|
||||||
<div class="ui bottom attached label">{{ part.number }} </div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
<div>
|
|
||||||
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{{ brset ? dump(brset) }}
|
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@ -1,21 +0,0 @@
|
|||||||
{% extends 'base.html.twig' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="ui seven column grid">
|
|
||||||
<div class="row">
|
|
||||||
{% for set in sets %}
|
|
||||||
<div class="column">
|
|
||||||
<a href="{{ url('set_detail', {'number': set.number, 'name' : set.name|escape('url') }) }}">
|
|
||||||
|
|
||||||
{#<img style="width: 100%" src="{{ set }}">#}
|
|
||||||
<p>{{ set.number }} - {{ set.name }}</p>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>{{ sets.getTotalItemCount }}</p>
|
|
||||||
|
|
||||||
{{ knp_pagination_render(sets) }}
|
|
||||||
{% endblock %}
|
|
46
app/Resources/views/rebrickable/set/parts.html.twig
Normal file
46
app/Resources/views/rebrickable/set/parts.html.twig
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
{% if regularParts|length > 0 %}
|
||||||
|
<h4 class="ui horizontal divider header">
|
||||||
|
Regular parts
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<div class="ui ten column grid">
|
||||||
|
{% for inventoryPart in regularParts %}
|
||||||
|
{% if inventoryPart.part is defined %}
|
||||||
|
<div class="column">
|
||||||
|
<div class="ui fluid bordered image">
|
||||||
|
<a class="ui right {{ inventoryPart.part.model == null ? 'black' : 'red'}} circular label">{{ inventoryPart.quantity }}</a>
|
||||||
|
<a href="{{ path('reb_part_detail', {number: inventoryPart.part.number}) }}">
|
||||||
|
<div class="image load">
|
||||||
|
<img src="{{ inventoryPart.part.number|partImage(inventoryPart.color.id)| imagine_filter('rebrickable_part_min') }}" data-src="{{ inventoryPart.part.number|partImage(inventoryPart.color.id)| imagine_filter('rebrickable_part_min') }}" class="transition visible">
|
||||||
|
</div>
|
||||||
|
<div style="border-bottom: #{{ inventoryPart.color.rgb }} 5px solid" class="ui bottom attached label">{{ inventoryPart.part.number }}</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if spareParts|length > 0 %}
|
||||||
|
<h4 class="ui horizontal divider header">
|
||||||
|
Spare parts
|
||||||
|
</h4>
|
||||||
|
<div class="ui ten column grid">
|
||||||
|
{% for inventoryPart in spareParts %}
|
||||||
|
{% if inventoryPart.part is defined %}
|
||||||
|
<div class="column">
|
||||||
|
<div class="ui fluid bordered image">
|
||||||
|
<a class="ui right {{ inventoryPart.part.model == null ? 'black' : 'red'}} circular label">{{ inventoryPart.quantity }}</a>
|
||||||
|
<a href="{{ path('reb_part_detail', {number: inventoryPart.part.number}) }}">
|
||||||
|
<div class="image load">
|
||||||
|
<img src="{{ inventoryPart.part.number|partImage(inventoryPart.color.id)| imagine_filter('rebrickable_part_min') }}" data-src="{{ inventoryPart.part.number|partImage(inventoryPart.color.id)| imagine_filter('rebrickable_part_min') }}" class="transition visible">
|
||||||
|
</div>
|
||||||
|
<div style="border-bottom: #{{ inventoryPart.color.rgb }} 5px solid" class="ui bottom attached label">{{ inventoryPart.part.number }}</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
16
app/Resources/views/rebrickable/set/sets.html.twig
Normal file
16
app/Resources/views/rebrickable/set/sets.html.twig
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<h4 class="ui horizontal divider header">Sets</h4>
|
||||||
|
<div class="ui seven column grid">
|
||||||
|
<div class="row">
|
||||||
|
{% for set in inventorySets %}
|
||||||
|
<div class="column">
|
||||||
|
<a href="{{ url('set_detail', {'number': set.set.number}) }}">
|
||||||
|
<div class="ui bordered image medium">
|
||||||
|
<img src="{{ asset('resources/images/unknown_image.png') }}" data-src="{{ set.set.number|setImage|imagine_filter('rebrickable_set_min') }}" class="transition visible">
|
||||||
|
</div>
|
||||||
|
<p>{{ set.set.number }} - {{ set.set.name }}</p>
|
||||||
|
<p>{{ set.quantity}}</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
138
app/Resources/views/set/detail.html.twig
Normal file
138
app/Resources/views/set/detail.html.twig
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
|
{% block title %}{{ rbset ? rbset.number }} {{ rbset ? rbset.name }}{% endblock %}
|
||||||
|
|
||||||
|
{% block header %}{{ rbset ? rbset.number }} {{ rbset ? rbset.name }}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="ui stackable grid">
|
||||||
|
<div class="column nine wide">
|
||||||
|
<div class="image bordered ui big">
|
||||||
|
{% if brset %}
|
||||||
|
<img class="big" src="{{ brset.imageURL }}">
|
||||||
|
{% elseif rbset %}
|
||||||
|
<img class="big" src="{{ rbset.number|setImage|imagine_filter('rebrickable') }}">
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column seven wide">
|
||||||
|
<div class="item-info black ui">
|
||||||
|
<table class="ui table">
|
||||||
|
<tr>
|
||||||
|
<td>number</td><td>{{ brset ? brset.legoSetID : rbset ? rbset.number : null}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>name</td><td>{{ brset ? brset.name : rbset ? rbset.name : null}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>year</td><td>{{ brset ? brset.year : rbset ? rbset.year : null}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>theme</td>
|
||||||
|
{% if rbset %}
|
||||||
|
<td><a href="#">{{ rbset.theme.parent ? rbset.theme.parent.name }}</a> <a href="#">{{ rbset.theme.name }}</a> </td>
|
||||||
|
{% elseif brset %}
|
||||||
|
<td>{{ brset.theme }}</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>parts</td><td>{{ brset ? brset.pieces : rbset ? rbset.partCount }}</td>
|
||||||
|
</tr>
|
||||||
|
{% if brset %}
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td><a class="brickset link" href="{{ brset.bricksetURL }}">Brickset</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
{% if rbset %}
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td><a class="rebrickable link" href="http://rebrickable.com/sets/{{ rbset ? rbset.number }}">Rebrickable</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{% if brset is not null %}
|
||||||
|
<dl>
|
||||||
|
<dt>themegroup:</dt><dd>{{ brset.themeGroup }}</dd>
|
||||||
|
<dt>theme:</dt><dd>{{ brset.theme }}</dd>
|
||||||
|
<dt>subtheme:</dt><dd>{{ brset.subtheme }}</dd>
|
||||||
|
<dt>count of parts:</dt><dd>{{ brset.pieces }}</dd>
|
||||||
|
<dt>minifigs:</dt><dd>{{ brset.minifigs }}</dd>
|
||||||
|
</dl>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="segment vertical item-info">
|
||||||
|
<div class="ui tabular menu">
|
||||||
|
<a class="item active" data-tab="parts"><i class="cubes icon"></i> Parts ({{ rbset ? rbset.partCount : 0}})</a>
|
||||||
|
{% if brset %}
|
||||||
|
<a class="item" data-tab="description"><i class="info icon"></i> Description</a>
|
||||||
|
<a class="item" data-tab="images"> <i class="image icon"></i> Images ({{ brset.additionalImageCount }})</a>
|
||||||
|
<a class="item" data-tab="instructions"> <i class="file pdf outline icon"></i> Instructions ({{ brset.instructionsCount }})</a>
|
||||||
|
<a class="item" data-tab="reviews"><i class="write icon"></i> Reviews ({{ brset.reviewCount }})</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="ui tab active" data-tab="parts">
|
||||||
|
{% if rbset %}
|
||||||
|
|
||||||
|
<div class="ajax-load" id="parts" data-src="{{ path('rebrickable_set_parts', { 'number': rbset.number }) }}"></div>
|
||||||
|
|
||||||
|
{#{{ render(controller('AppBundle:Rebrickable/Set:parts', { 'number': rbset.number })) }}#}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% if brset %}
|
||||||
|
<div class="ui tab" data-tab="images">
|
||||||
|
{#<div class="ajax-load" id="images" data-src="{{ path('brickset_images', { 'id': brset.setID }) }}"></div>#}
|
||||||
|
|
||||||
|
{{ render(controller('AppBundle:Brickset/Set:images', { 'id': brset.setID })) }}
|
||||||
|
</div>
|
||||||
|
<div class="ui tab" data-tab="instructions">
|
||||||
|
{#<div class="ajax-load" id="instructions" data-src="{{ path('brickset_instructions', { 'id': brset.setID }) }}"></div>#}
|
||||||
|
|
||||||
|
{{ render(controller('AppBundle:Brickset/Set:instructions', { 'id': brset.setID })) }}
|
||||||
|
</div>
|
||||||
|
<div class="ui tab" data-tab="reviews">
|
||||||
|
{#<div class="ajax-load" id="reviews" data-src="{{ path('brickset_reviews', { 'id': brset.setID }) }}"></div>#}
|
||||||
|
|
||||||
|
{{ render(controller('AppBundle:Brickset/Set:reviews', { 'id': brset.setID })) }}
|
||||||
|
</div>
|
||||||
|
<div class="ui tab" data-tab="description">
|
||||||
|
{{ brset.description }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
{{ parent() }}
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
|
||||||
|
$('.ajax-load').each(function () {
|
||||||
|
$self = $(this);
|
||||||
|
|
||||||
|
console.log($self);
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
dataType: 'json',
|
||||||
|
url: $self.data('src'),
|
||||||
|
async: true, //you won't need that if nothing in your following code is dependend of the result
|
||||||
|
success: function(response){
|
||||||
|
$self.html(response); //Change the html of the div with the id = "your_div"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
36
app/Resources/views/set/index.html.twig
Normal file
36
app/Resources/views/set/index.html.twig
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<form method="get" action="" class="ui form">
|
||||||
|
{{ form_start(form) }}
|
||||||
|
|
||||||
|
{{ form_row(form.search) }}
|
||||||
|
<div class="field fluid search selection">
|
||||||
|
{{ form_label(form.theme.id) }}
|
||||||
|
{{ form_widget(form.theme.id) }}
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<input class="ui submit button" type="submit" value="filter"/>
|
||||||
|
</div>
|
||||||
|
{{ form_rest(form) }}
|
||||||
|
{{ form_end(form) }}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="ui seven column grid">
|
||||||
|
<div class="row">
|
||||||
|
{% for set in sets %}
|
||||||
|
<div class="column">
|
||||||
|
<a href="{{ url('set_detail', {'number': set.number, 'name' : set.name|escape('url') }) }}">
|
||||||
|
<img class="ui bordered image medium" src="{{ set.number|setImage|imagine_filter('rebrickable_set_min') }}">
|
||||||
|
<p>{{ set.number }} - {{ set.name }}</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>{{ sets.getTotalItemCount }}</p>
|
||||||
|
|
||||||
|
{{ knp_pagination_render(sets) }}
|
||||||
|
{% endblock %}
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Doctrine\Common\Annotations\AnnotationRegistry;
|
|
||||||
use Composer\Autoload\ClassLoader;
|
use Composer\Autoload\ClassLoader;
|
||||||
|
use Doctrine\Common\Annotations\AnnotationRegistry;
|
||||||
|
|
||||||
/** @var ClassLoader $loader */
|
/** @var ClassLoader $loader */
|
||||||
$loader = require __DIR__.'/../vendor/autoload.php';
|
$loader = require __DIR__.'/../vendor/autoload.php';
|
||||||
|
2564
app/config/brickset.xml
Normal file
2564
app/config/brickset.xml
Normal file
File diff suppressed because it is too large
Load Diff
@ -7,10 +7,8 @@ imports:
|
|||||||
# http://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
|
# http://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
|
||||||
parameters:
|
parameters:
|
||||||
locale: en
|
locale: en
|
||||||
# rebrickable csv files root URL
|
# rebrickable csv files root URL (http://rebrickable.com/media/downloads/ or local dir containing csv files)
|
||||||
rebrickable_url: 'http://rebrickable.com/media/downloads/'
|
rebrickable_csv_url: 'http://rebrickable.com/media/downloads/'
|
||||||
# LDraw library zip file URL
|
|
||||||
ldraw_url: 'http://www.ldraw.org/library/updates/complete.zip'
|
|
||||||
|
|
||||||
framework:
|
framework:
|
||||||
#esi: ~
|
#esi: ~
|
||||||
@ -92,11 +90,56 @@ knp_paginator:
|
|||||||
pagination: KnpPaginatorBundle:Pagination:semantic_ui_pagination.html.twig # sliding pagination controls template
|
pagination: KnpPaginatorBundle:Pagination:semantic_ui_pagination.html.twig # sliding pagination controls template
|
||||||
sortable: KnpPaginatorBundle:Pagination:sortable_link.html.twig # sort link template
|
sortable: KnpPaginatorBundle:Pagination:sortable_link.html.twig # sort link template
|
||||||
|
|
||||||
|
liip_imagine:
|
||||||
|
loaders:
|
||||||
|
media:
|
||||||
|
flysystem:
|
||||||
|
filesystem_service: oneup_flysystem.media_filesystem
|
||||||
|
rebrickable:
|
||||||
|
stream:
|
||||||
|
wrapper: 'http://m.rebrickable.com/media/'
|
||||||
|
|
||||||
|
resolvers:
|
||||||
|
default:
|
||||||
|
web_path: ~
|
||||||
|
|
||||||
|
filter_sets:
|
||||||
|
model_min:
|
||||||
|
data_loader: media
|
||||||
|
cache: ~
|
||||||
|
quality: 80
|
||||||
|
default_image: '/resources/images/unknown_image.png'
|
||||||
|
filters:
|
||||||
|
thumbnail: { size: [200, 200], mode: inset }
|
||||||
|
background: { size: [250, 250], position: center, color: '#FFFFFF' }
|
||||||
|
model_large:
|
||||||
|
data_loader: media
|
||||||
|
cache: ~
|
||||||
|
quality: 92
|
||||||
|
filters:
|
||||||
|
thumbnail: { size: [800, 600], mode: inset }
|
||||||
|
background: { size: [1100, 800], position: center, color: '#FFFFFF' }
|
||||||
|
rebrickable:
|
||||||
|
data_loader: rebrickable
|
||||||
|
rebrickable_part_min:
|
||||||
|
quality: 80
|
||||||
|
data_loader: rebrickable
|
||||||
|
cache: ~
|
||||||
|
default_image: '/resources/images/unknown_image.png'
|
||||||
|
filters:
|
||||||
|
thumbnail: { size: [250, 250], mode: inset }
|
||||||
|
rebrickable_set_min:
|
||||||
|
quality: 80
|
||||||
|
data_loader: rebrickable
|
||||||
|
default_image: '/resources/images/unknown_image.png'
|
||||||
|
cache: ~
|
||||||
|
filters:
|
||||||
|
thumbnail: { size: [250, 250], mode: inset }
|
||||||
oneup_flysystem:
|
oneup_flysystem:
|
||||||
adapters:
|
adapters:
|
||||||
media_adapter:
|
media:
|
||||||
local:
|
local:
|
||||||
directory: "%kernel.root_dir%/../var/media/"
|
directory: "%kernel.root_dir%/../var/media/"
|
||||||
filesystems:
|
filesystems:
|
||||||
media:
|
media:
|
||||||
adapter: media_adapter
|
adapter: media
|
@ -12,15 +12,22 @@ web_profiler:
|
|||||||
intercept_redirects: false
|
intercept_redirects: false
|
||||||
|
|
||||||
monolog:
|
monolog:
|
||||||
|
channels: ['loader']
|
||||||
handlers:
|
handlers:
|
||||||
main:
|
main:
|
||||||
type: stream
|
type: stream
|
||||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||||
level: debug
|
level: debug
|
||||||
channels: [!event]
|
channels: [!event, !loader]
|
||||||
console:
|
console:
|
||||||
type: console
|
type: console
|
||||||
channels: [!event, !doctrine]
|
channels: [!event, !doctrine]
|
||||||
|
loader:
|
||||||
|
type: rotating_file
|
||||||
|
path: "%kernel.logs_dir%/loader.log"
|
||||||
|
level: debug
|
||||||
|
channels: 'loader'
|
||||||
|
max_files: 10
|
||||||
# uncomment to get logging in your browser
|
# uncomment to get logging in your browser
|
||||||
# you may have to allow bigger header sizes in your Web server configuration
|
# you may have to allow bigger header sizes in your Web server configuration
|
||||||
#firephp:
|
#firephp:
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
app:
|
app:
|
||||||
resource: "@AppBundle/Controller/"
|
resource: "@AppBundle/Controller/"
|
||||||
type: annotation
|
type: annotation
|
||||||
|
_liip_imagine:
|
||||||
|
resource: "@LiipImagineBundle/Resources/config/routing.xml"
|
@ -1,7 +1,7 @@
|
|||||||
services:
|
services:
|
||||||
api.client.brickset:
|
api.client.brickset:
|
||||||
class: AppBundle\Api\Client\Brickset\Brickset
|
class: AppBundle\Api\Client\Brickset\Brickset
|
||||||
arguments: ['%brickset_apikey%']
|
arguments: ['%brickset_apikey%', '%kernel.root_dir%/config/brickset.xml']
|
||||||
api.client.rebrickable:
|
api.client.rebrickable:
|
||||||
class: AppBundle\Api\Client\Rebrickable\Rebrickable_v3
|
class: AppBundle\Api\Client\Rebrickable\Rebrickable_v3
|
||||||
arguments: ['%rebrickable_apikey%']
|
arguments: ['%rebrickable_apikey%']
|
||||||
|
@ -1,7 +1,20 @@
|
|||||||
services:
|
services:
|
||||||
form.filter.category:
|
form.filter.category:
|
||||||
class: AppBundle\Form\Filter\CategoryFilterType
|
class: AppBundle\Form\Filter\Model\CategoryFilterType
|
||||||
arguments:
|
arguments:
|
||||||
- '@manager.ldraw.category'
|
- '@repository.ldraw.category'
|
||||||
tags:
|
tags:
|
||||||
- { name: form.type }
|
- { name: form.type }
|
||||||
|
|
||||||
|
form.filter.brickset:
|
||||||
|
class: AppBundle\Form\FilterSetType
|
||||||
|
arguments: ['@api.manager.brickset']
|
||||||
|
tags:
|
||||||
|
- { name: form.type }
|
||||||
|
|
||||||
|
form.filter.theme:
|
||||||
|
class: AppBundle\Form\Filter\Set\ThemeFilterType
|
||||||
|
arguments:
|
||||||
|
- '@repository.rebrickable.theme'
|
||||||
|
tags:
|
||||||
|
- { name: form.type }
|
||||||
|
@ -1,29 +1,25 @@
|
|||||||
services:
|
services:
|
||||||
service.loader:
|
service.loader.base:
|
||||||
abstract: true
|
abstract: true
|
||||||
class: AppBundle\Service\Loader\BaseLoaderService
|
class: AppBundle\Service\Loader\BaseLoader
|
||||||
calls:
|
calls:
|
||||||
- [setArguments, ['@doctrine.orm.entity_manager', '@app.relation.mapper']]
|
- [setArguments, ['@doctrine.orm.entity_manager', '@monolog.logger.loader']]
|
||||||
|
|
||||||
service.ldview:
|
service.ldview:
|
||||||
class: AppBundle\Service\LDViewService
|
class: AppBundle\Service\LDViewService
|
||||||
arguments: ['%ldview_bin%', '@oneup_flysystem.media_filesystem']
|
arguments: ['%ldview_bin%', '@oneup_flysystem.media_filesystem']
|
||||||
|
|
||||||
service.loader.rebrickable:
|
service.loader.rebrickable:
|
||||||
class: AppBundle\Service\Loader\RebrickableLoaderService
|
class: AppBundle\Service\Loader\RebrickableLoader
|
||||||
arguments: ['%rebrickable_url%']
|
arguments: ['%rebrickable_csv_url%']
|
||||||
parent: service.loader
|
parent: service.loader.base
|
||||||
|
|
||||||
util.dat.parser:
|
service.loader.model:
|
||||||
class: AppBundle\Utils\DatParser
|
class: AppBundle\Service\Loader\ModelLoader
|
||||||
arguments: ['@app.relation.mapper']
|
arguments: ['@service.ldview', '@app.relation.mapper']
|
||||||
|
parent: service.loader.base
|
||||||
service.loader.ldraw:
|
|
||||||
class: AppBundle\Service\Loader\LDrawLoaderService
|
|
||||||
arguments: ['@service.ldview', '%ldraw_url%', '@manager.ldraw', '@util.dat.parser']
|
|
||||||
parent: service.loader
|
|
||||||
|
|
||||||
service.loader.relation:
|
service.loader.relation:
|
||||||
class: AppBundle\Service\Loader\RelationLoader
|
class: AppBundle\Service\Loader\RelationLoader
|
||||||
arguments: ['@manager.ldraw.model', '@repository.rebrickable.part', '@api.manager.rebrickable']
|
arguments: ['@api.manager.rebrickable', '@app.relation.mapper']
|
||||||
parent: service.loader
|
parent: service.loader.base
|
@ -1,28 +1 @@
|
|||||||
services:
|
services:
|
||||||
manager.ldraw.keyword:
|
|
||||||
class: AppBundle\Manager\LDraw\KeywordManager
|
|
||||||
arguments:
|
|
||||||
- "@repository.ldraw.keyword"
|
|
||||||
manager.ldraw.category:
|
|
||||||
class: AppBundle\Manager\LDraw\CategoryManager
|
|
||||||
arguments:
|
|
||||||
- "@repository.ldraw.category"
|
|
||||||
manager.ldraw.type:
|
|
||||||
class: AppBundle\Manager\LDraw\TypeManager
|
|
||||||
arguments:
|
|
||||||
- "@repository.ldraw.type"
|
|
||||||
manager.ldraw.subpart:
|
|
||||||
class: AppBundle\Manager\LDraw\SubpartManager
|
|
||||||
arguments:
|
|
||||||
- "@repository.ldraw.subpart"
|
|
||||||
manager.ldraw.model:
|
|
||||||
class: AppBundle\Manager\LDraw\ModelManager
|
|
||||||
arguments:
|
|
||||||
- "@repository.ldraw.model"
|
|
||||||
manager.ldraw.alias:
|
|
||||||
class: AppBundle\Manager\LDraw\AliasManager
|
|
||||||
arguments:
|
|
||||||
- "@repository.ldraw.alias"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -41,6 +41,13 @@ services:
|
|||||||
arguments:
|
arguments:
|
||||||
- AppBundle\Entity\LDraw\Alias
|
- AppBundle\Entity\LDraw\Alias
|
||||||
|
|
||||||
|
repository.ldraw.author:
|
||||||
|
class: Doctrine\ORM\EntityRepository
|
||||||
|
factory: ["@doctrine", getRepository]
|
||||||
|
arguments:
|
||||||
|
- AppBundle\Entity\LDraw\Author
|
||||||
|
|
||||||
|
|
||||||
repository.rebrickable.category:
|
repository.rebrickable.category:
|
||||||
class: Doctrine\ORM\EntityRepository
|
class: Doctrine\ORM\EntityRepository
|
||||||
factory: ["@doctrine", getRepository]
|
factory: ["@doctrine", getRepository]
|
||||||
|
@ -1,19 +1,10 @@
|
|||||||
services:
|
services:
|
||||||
manager.ldraw:
|
app.twig_extension:
|
||||||
class: AppBundle\Manager\LDrawManager
|
class: AppBundle\Twig\AppExtension
|
||||||
arguments:
|
public: false
|
||||||
- '@manager.ldraw.category'
|
arguments: ['@api.manager.rebrickable']
|
||||||
- '@manager.ldraw.keyword'
|
|
||||||
- '@manager.ldraw.type'
|
|
||||||
- '@manager.ldraw.subpart'
|
|
||||||
- '@manager.ldraw.model'
|
|
||||||
- '@manager.ldraw.alias'
|
|
||||||
|
|
||||||
app.form.filter_set:
|
|
||||||
class: AppBundle\Form\FilterSetType
|
|
||||||
arguments: ['@api.manager.brickset']
|
|
||||||
tags:
|
tags:
|
||||||
- { name: form.type }
|
- { name: twig.extension }
|
||||||
|
|
||||||
app.relation.mapper:
|
app.relation.mapper:
|
||||||
class: AppBundle\Utils\RelationMapper
|
class: AppBundle\Utils\RelationMapper
|
||||||
|
@ -23,10 +23,11 @@
|
|||||||
"sensio/framework-extra-bundle": "^3.0.2",
|
"sensio/framework-extra-bundle": "^3.0.2",
|
||||||
"incenteev/composer-parameter-handler": "^2.0",
|
"incenteev/composer-parameter-handler": "^2.0",
|
||||||
"guzzlehttp/guzzle": "^6.2",
|
"guzzlehttp/guzzle": "^6.2",
|
||||||
"knplabs/knp-menu-bundle": "^2.0",
|
"knplabs/knp-menu-bundle": "^2.1",
|
||||||
"oneup/flysystem-bundle": "^1.7",
|
"oneup/flysystem-bundle": "^1.7",
|
||||||
"knplabs/knp-paginator-bundle": "^2.5",
|
"knplabs/knp-paginator-bundle": "^2.5",
|
||||||
"lexik/form-filter-bundle": "~5.0"
|
"lexik/form-filter-bundle": "~5.0",
|
||||||
|
"liip/imagine-bundle": "^1.7"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"sensio/generator-bundle": "^3.0",
|
"sensio/generator-bundle": "^3.0",
|
||||||
|
441
composer.lock
generated
441
composer.lock
generated
@ -4,8 +4,67 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "6956e65252fd75b8d2e258fcc54fa3a9",
|
"content-hash": "6a70240b303126447c6fc3c6f75bf6ff",
|
||||||
"packages": [
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "composer/ca-bundle",
|
||||||
|
"version": "1.0.7",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/composer/ca-bundle.git",
|
||||||
|
"reference": "b17e6153cb7f33c7e44eb59578dc12eee5dc8e12"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/b17e6153cb7f33c7e44eb59578dc12eee5dc8e12",
|
||||||
|
"reference": "b17e6153cb7f33c7e44eb59578dc12eee5dc8e12",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-openssl": "*",
|
||||||
|
"ext-pcre": "*",
|
||||||
|
"php": "^5.3.2 || ^7.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^4.5",
|
||||||
|
"psr/log": "^1.0",
|
||||||
|
"symfony/process": "^2.5 || ^3.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"symfony/process": "This is necessary to reliably check whether openssl_x509_parse is vulnerable on older php versions, but can be ignored on PHP 5.5.6+"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Composer\\CaBundle\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Jordi Boggiano",
|
||||||
|
"email": "j.boggiano@seld.be",
|
||||||
|
"homepage": "http://seld.be"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
|
||||||
|
"keywords": [
|
||||||
|
"cabundle",
|
||||||
|
"cacert",
|
||||||
|
"certificate",
|
||||||
|
"ssl",
|
||||||
|
"tls"
|
||||||
|
],
|
||||||
|
"time": "2017-03-06T11:59:08+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/annotations",
|
"name": "doctrine/annotations",
|
||||||
"version": "v1.2.7",
|
"version": "v1.2.7",
|
||||||
@ -952,6 +1011,63 @@
|
|||||||
],
|
],
|
||||||
"time": "2017-03-20T17:10:46+00:00"
|
"time": "2017-03-20T17:10:46+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "imagine/imagine",
|
||||||
|
"version": "v0.6.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/avalanche123/Imagine.git",
|
||||||
|
"reference": "149041d2a1b517107bfe270ca2b1a17aa341715d"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/avalanche123/Imagine/zipball/149041d2a1b517107bfe270ca2b1a17aa341715d",
|
||||||
|
"reference": "149041d2a1b517107bfe270ca2b1a17aa341715d",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.2"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"sami/sami": "dev-master"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-gd": "to use the GD implementation",
|
||||||
|
"ext-gmagick": "to use the Gmagick implementation",
|
||||||
|
"ext-imagick": "to use the Imagick implementation"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-develop": "0.7-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"Imagine": "lib/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Bulat Shakirzyanov",
|
||||||
|
"email": "mallluhuct@gmail.com",
|
||||||
|
"homepage": "http://avalanche123.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Image processing for PHP 5.3",
|
||||||
|
"homepage": "http://imagine.readthedocs.org/",
|
||||||
|
"keywords": [
|
||||||
|
"drawing",
|
||||||
|
"graphics",
|
||||||
|
"image manipulation",
|
||||||
|
"image processing"
|
||||||
|
],
|
||||||
|
"time": "2015-09-19T16:54:05+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "incenteev/composer-parameter-handler",
|
"name": "incenteev/composer-parameter-handler",
|
||||||
"version": "v2.1.2",
|
"version": "v2.1.2",
|
||||||
@ -1053,6 +1169,94 @@
|
|||||||
],
|
],
|
||||||
"time": "2014-01-12T16:20:24+00:00"
|
"time": "2014-01-12T16:20:24+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "knplabs/gaufrette",
|
||||||
|
"version": "v0.3.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/KnpLabs/Gaufrette.git",
|
||||||
|
"reference": "771ad16f4b2e7f9d35f44b201956e83c6fbf5dde"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/KnpLabs/Gaufrette/zipball/771ad16f4b2e7f9d35f44b201956e83c6fbf5dde",
|
||||||
|
"reference": "771ad16f4b2e7f9d35f44b201956e83c6fbf5dde",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.4"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"microsoft/windowsazure": "<0.4.3"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"amazonwebservices/aws-sdk-for-php": "1.5.*",
|
||||||
|
"aws/aws-sdk-php": "^2.4.12",
|
||||||
|
"doctrine/dbal": ">=2.3",
|
||||||
|
"dropbox-php/dropbox-php": "*",
|
||||||
|
"google/apiclient": "~1.1.3",
|
||||||
|
"herzult/php-ssh": "*",
|
||||||
|
"league/flysystem": "~1.0",
|
||||||
|
"mikey179/vfsstream": "~1.2.0",
|
||||||
|
"phpseclib/phpseclib": "^2.0",
|
||||||
|
"phpspec/phpspec": "~2.4",
|
||||||
|
"phpunit/phpunit": "3.7.*",
|
||||||
|
"rackspace/php-opencloud": "^1.9.2"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"amazonwebservices/aws-sdk-for-php": "to use the legacy Amazon S3 adapters",
|
||||||
|
"aws/aws-sdk-php": "to use the Amazon S3 adapter",
|
||||||
|
"doctrine/dbal": "to use the Doctrine DBAL adapter",
|
||||||
|
"dropbox-php/dropbox-php": "to use the Dropbox adapter",
|
||||||
|
"ext-apc": "to use the APC adapter",
|
||||||
|
"ext-curl": "*",
|
||||||
|
"ext-fileinfo": "This extension is used to automatically detect the content-type of a file in the AwsS3, OpenCloud, AzureBlogStorage and GoogleCloudStorage adapters",
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"ext-mongo": "*",
|
||||||
|
"ext-zip": "to use the Zip adapter",
|
||||||
|
"google/apiclient": "to use GoogleCloudStorage adapter",
|
||||||
|
"herzult/php-ssh": "to use SFtp adapter",
|
||||||
|
"knplabs/knp-gaufrette-bundle": "to use with Symfony2",
|
||||||
|
"league/flysystem": "to use Flysystem adapters",
|
||||||
|
"microsoft/windowsazure": "to use Microsoft Azure Blob Storage adapter",
|
||||||
|
"phpseclib/phpseclib": "to use PhpseclibSftp adapter",
|
||||||
|
"rackspace/php-opencloud": "to use Opencloud adapter"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "0.4.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"Gaufrette": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "The contributors",
|
||||||
|
"homepage": "http://github.com/knplabs/Gaufrette/contributors"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "KnpLabs Team",
|
||||||
|
"homepage": "http://knplabs.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PHP5 library that provides a filesystem abstraction layer",
|
||||||
|
"homepage": "http://knplabs.com",
|
||||||
|
"keywords": [
|
||||||
|
"abstraction",
|
||||||
|
"file",
|
||||||
|
"filesystem",
|
||||||
|
"media"
|
||||||
|
],
|
||||||
|
"time": "2017-03-20T01:23:34+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "knplabs/knp-components",
|
"name": "knplabs/knp-components",
|
||||||
"version": "1.3.4",
|
"version": "1.3.4",
|
||||||
@ -1124,6 +1328,64 @@
|
|||||||
],
|
],
|
||||||
"time": "2016-12-06T18:10:24+00:00"
|
"time": "2016-12-06T18:10:24+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "knplabs/knp-gaufrette-bundle",
|
||||||
|
"version": "v0.4.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/KnpLabs/KnpGaufretteBundle.git",
|
||||||
|
"reference": "06d91a8a575773cd0361c1246c9c499b6bdd5d68"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/KnpLabs/KnpGaufretteBundle/zipball/06d91a8a575773cd0361c1246c9c499b6bdd5d68",
|
||||||
|
"reference": "06d91a8a575773cd0361c1246c9c499b6bdd5d68",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"knplabs/gaufrette": "~0.1.7|~0.2|~0.3",
|
||||||
|
"symfony/framework-bundle": "~2.0|~3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "~4.2",
|
||||||
|
"symfony/console": "~2.0|~3.0",
|
||||||
|
"symfony/yaml": "~2.0|~3.0"
|
||||||
|
},
|
||||||
|
"type": "symfony-bundle",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "0.4.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Knp\\Bundle\\GaufretteBundle\\": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "The contributors",
|
||||||
|
"homepage": "https://github.com/knplabs/KnpGaufretteBundle/contributors"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Antoine Hérault",
|
||||||
|
"email": "antoine.herault@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Allows to easily use the Gaufrette library in a Symfony project",
|
||||||
|
"homepage": "http://knplabs.com",
|
||||||
|
"keywords": [
|
||||||
|
"abstraction",
|
||||||
|
"file",
|
||||||
|
"filesystem",
|
||||||
|
"media"
|
||||||
|
],
|
||||||
|
"time": "2017-03-16T21:01:25+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "knplabs/knp-menu",
|
"name": "knplabs/knp-menu",
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
@ -1394,16 +1656,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "lexik/form-filter-bundle",
|
"name": "lexik/form-filter-bundle",
|
||||||
"version": "v5.0.3",
|
"version": "v5.0.4",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/lexik/LexikFormFilterBundle.git",
|
"url": "https://github.com/lexik/LexikFormFilterBundle.git",
|
||||||
"reference": "124a6c8e9eb109e7616a18d916bbc33137bb308d"
|
"reference": "28c09d6d9f278875ca9648c4b66eeb457c37d3b6"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/lexik/LexikFormFilterBundle/zipball/124a6c8e9eb109e7616a18d916bbc33137bb308d",
|
"url": "https://api.github.com/repos/lexik/LexikFormFilterBundle/zipball/28c09d6d9f278875ca9648c4b66eeb457c37d3b6",
|
||||||
"reference": "124a6c8e9eb109e7616a18d916bbc33137bb308d",
|
"reference": "28c09d6d9f278875ca9648c4b66eeb457c37d3b6",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -1444,13 +1706,113 @@
|
|||||||
"description": "This bundle aim to provide classes to build some form filters and then build a doctrine query from this form filter.",
|
"description": "This bundle aim to provide classes to build some form filters and then build a doctrine query from this form filter.",
|
||||||
"homepage": "https://github.com/lexik/LexikFormFilterBundle",
|
"homepage": "https://github.com/lexik/LexikFormFilterBundle",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Symfony2",
|
|
||||||
"bundle",
|
"bundle",
|
||||||
"doctrine",
|
"doctrine",
|
||||||
"filter",
|
"filter",
|
||||||
"form"
|
"form",
|
||||||
|
"symfony"
|
||||||
],
|
],
|
||||||
"time": "2017-01-24T13:03:45+00:00"
|
"time": "2017-03-27T07:28:34+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "liip/imagine-bundle",
|
||||||
|
"version": "1.7.4",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/liip/LiipImagineBundle.git",
|
||||||
|
"reference": "105dd9c3446e3eb44e33161d4e636a3abafb6d7f"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/liip/LiipImagineBundle/zipball/105dd9c3446e3eb44e33161d4e636a3abafb6d7f",
|
||||||
|
"reference": "105dd9c3446e3eb44e33161d4e636a3abafb6d7f",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"imagine/imagine": "^0.6.3,<0.7",
|
||||||
|
"php": "^5.3.9|^7.0",
|
||||||
|
"symfony/asset": "~2.3|~3.0",
|
||||||
|
"symfony/filesystem": "~2.3|~3.0",
|
||||||
|
"symfony/finder": "~2.3|~3.0",
|
||||||
|
"symfony/framework-bundle": "~2.3|~3.0",
|
||||||
|
"symfony/options-resolver": "~2.3|~3.0",
|
||||||
|
"symfony/process": "~2.3|~3.0",
|
||||||
|
"symfony/templating": "~2.3|~3.0",
|
||||||
|
"symfony/translation": "~2.3|~3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"amazonwebservices/aws-sdk-for-php": "~1.0",
|
||||||
|
"aws/aws-sdk-php": "~2.4",
|
||||||
|
"doctrine/cache": "~1.1",
|
||||||
|
"doctrine/orm": "~2.3",
|
||||||
|
"ext-gd": "*",
|
||||||
|
"friendsofphp/php-cs-fixer": "~2.0",
|
||||||
|
"phpunit/phpunit": "~4.3|~5.0",
|
||||||
|
"psr/log": "~1.0",
|
||||||
|
"satooshi/php-coveralls": "~1.0",
|
||||||
|
"sllh/php-cs-fixer-styleci-bridge": "~2.1",
|
||||||
|
"symfony/browser-kit": "~2.3|~3.0",
|
||||||
|
"symfony/console": "~2.3|~3.0",
|
||||||
|
"symfony/dependency-injection": "~2.3|~3.0",
|
||||||
|
"symfony/form": "~2.3|~3.0",
|
||||||
|
"symfony/phpunit-bridge": "~2.3|~3.0",
|
||||||
|
"symfony/validator": "~2.3|~3.0",
|
||||||
|
"symfony/yaml": "~2.3|~3.0",
|
||||||
|
"twig/twig": "~1.12|~2.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"alcaeus/mongo-php-adapter": "required on PHP >= 7.0 to use mongo components with mongodb extension",
|
||||||
|
"amazonwebservices/aws-sdk-for-php": "required to use AWS version 1 cache resolver",
|
||||||
|
"aws/aws-sdk-php": "required to use AWS version 2/3 cache resolver",
|
||||||
|
"doctrine/mongodb-odm": "required to use mongodb-backed doctrine components",
|
||||||
|
"ext-exif": "required to read EXIF metadata from images",
|
||||||
|
"ext-gd": "required to use gd driver",
|
||||||
|
"ext-gmagick": "required to use gmagick driver",
|
||||||
|
"ext-imagick": "required to use imagick driver",
|
||||||
|
"ext-mongo": "required for mongodb components on PHP <7.0",
|
||||||
|
"ext-mongodb": "required for mongodb components on PHP >=7.0",
|
||||||
|
"league/flysystem": "required to use FlySystem data loader or cache resolver",
|
||||||
|
"monolog/monolog": "A psr/log compatible logger is required to enable logging",
|
||||||
|
"twig/twig": "required to use the provided Twig extension. Version 1.12 or greater needed"
|
||||||
|
},
|
||||||
|
"type": "symfony-bundle",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-1.0": "1.7-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Liip\\ImagineBundle\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Liip and other contributors",
|
||||||
|
"homepage": "https://github.com/liip/LiipImagineBundle/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "This bundle provides an image manipulation abstraction toolkit for Symfony-based projects.",
|
||||||
|
"homepage": "http://liip.ch",
|
||||||
|
"keywords": [
|
||||||
|
"bundle",
|
||||||
|
"image",
|
||||||
|
"imagine",
|
||||||
|
"liip",
|
||||||
|
"manipulation",
|
||||||
|
"photos",
|
||||||
|
"pictures",
|
||||||
|
"symfony",
|
||||||
|
"transformation"
|
||||||
|
],
|
||||||
|
"time": "2017-03-02T20:18:55+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "monolog/monolog",
|
"name": "monolog/monolog",
|
||||||
@ -1532,16 +1894,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "oneup/flysystem-bundle",
|
"name": "oneup/flysystem-bundle",
|
||||||
"version": "1.11.0",
|
"version": "1.12.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/1up-lab/OneupFlysystemBundle.git",
|
"url": "https://github.com/1up-lab/OneupFlysystemBundle.git",
|
||||||
"reference": "a68f83415e3af2313c529be6b22bfddfcfe8e90f"
|
"reference": "2addd1077360790a7722fef09388a003576d585c"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/1up-lab/OneupFlysystemBundle/zipball/a68f83415e3af2313c529be6b22bfddfcfe8e90f",
|
"url": "https://api.github.com/repos/1up-lab/OneupFlysystemBundle/zipball/2addd1077360790a7722fef09388a003576d585c",
|
||||||
"reference": "a68f83415e3af2313c529be6b22bfddfcfe8e90f",
|
"reference": "2addd1077360790a7722fef09388a003576d585c",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -1562,6 +1924,7 @@
|
|||||||
"league/flysystem-ziparchive": "~1.0",
|
"league/flysystem-ziparchive": "~1.0",
|
||||||
"litipk/flysystem-fallback-adapter": "~0.1",
|
"litipk/flysystem-fallback-adapter": "~0.1",
|
||||||
"phpunit/phpunit": "^4.4",
|
"phpunit/phpunit": "^4.4",
|
||||||
|
"superbalist/flysystem-google-storage": "~4.0",
|
||||||
"symfony/asset": "~2.0|~3.0",
|
"symfony/asset": "~2.0|~3.0",
|
||||||
"symfony/browser-kit": "~2.0|~3.0",
|
"symfony/browser-kit": "~2.0|~3.0",
|
||||||
"symfony/finder": "~2.0|~3.0",
|
"symfony/finder": "~2.0|~3.0",
|
||||||
@ -1583,6 +1946,7 @@
|
|||||||
"league/flysystem-webdav": "Allows you to use WebDAV storage",
|
"league/flysystem-webdav": "Allows you to use WebDAV storage",
|
||||||
"league/flysystem-ziparchive": "Allows you to use ZipArchive adapter",
|
"league/flysystem-ziparchive": "Allows you to use ZipArchive adapter",
|
||||||
"litipk/flysystem-fallback-adapter": "Allows you to use a fallback filesystem",
|
"litipk/flysystem-fallback-adapter": "Allows you to use a fallback filesystem",
|
||||||
|
"superbalist/flysystem-google-storage": "Allows you to use Google Cloud Storage buckets",
|
||||||
"twistor/flysystem-stream-wrapper": "Allows you to use stream wrapper"
|
"twistor/flysystem-stream-wrapper": "Allows you to use stream wrapper"
|
||||||
},
|
},
|
||||||
"type": "symfony-bundle",
|
"type": "symfony-bundle",
|
||||||
@ -1611,7 +1975,7 @@
|
|||||||
"abstraction",
|
"abstraction",
|
||||||
"filesystem"
|
"filesystem"
|
||||||
],
|
],
|
||||||
"time": "2017-03-03T13:41:53+00:00"
|
"time": "2017-03-27T08:48:46+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "paragonie/random_compat",
|
"name": "paragonie/random_compat",
|
||||||
@ -1928,19 +2292,20 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sensiolabs/security-checker",
|
"name": "sensiolabs/security-checker",
|
||||||
"version": "v4.0.2",
|
"version": "v4.0.4",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sensiolabs/security-checker.git",
|
"url": "https://github.com/sensiolabs/security-checker.git",
|
||||||
"reference": "56bded66985e22f6eac2cf86735fd21c625bff2f"
|
"reference": "9e69eddf3bc49d1ee5c7908564da3141796d4bbc"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sensiolabs/security-checker/zipball/56bded66985e22f6eac2cf86735fd21c625bff2f",
|
"url": "https://api.github.com/repos/sensiolabs/security-checker/zipball/9e69eddf3bc49d1ee5c7908564da3141796d4bbc",
|
||||||
"reference": "56bded66985e22f6eac2cf86735fd21c625bff2f",
|
"reference": "9e69eddf3bc49d1ee5c7908564da3141796d4bbc",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
"composer/ca-bundle": "^1.0",
|
||||||
"symfony/console": "~2.7|~3.0"
|
"symfony/console": "~2.7|~3.0"
|
||||||
},
|
},
|
||||||
"bin": [
|
"bin": [
|
||||||
@ -1968,7 +2333,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "A security checker for your composer.lock",
|
"description": "A security checker for your composer.lock",
|
||||||
"time": "2017-03-09T17:33:20+00:00"
|
"time": "2017-03-31T14:50:32+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "swiftmailer/swiftmailer",
|
"name": "swiftmailer/swiftmailer",
|
||||||
@ -2482,16 +2847,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/symfony",
|
"name": "symfony/symfony",
|
||||||
"version": "v3.2.6",
|
"version": "v3.2.7",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/symfony.git",
|
"url": "https://github.com/symfony/symfony.git",
|
||||||
"reference": "b0f8a7fa4b8baadf9db299cb6ac87c96a8977dbe"
|
"reference": "1631040ea8fc5e0e405c00d35cbf2c0b7b555f64"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/symfony/zipball/b0f8a7fa4b8baadf9db299cb6ac87c96a8977dbe",
|
"url": "https://api.github.com/repos/symfony/symfony/zipball/1631040ea8fc5e0e405c00d35cbf2c0b7b555f64",
|
||||||
"reference": "b0f8a7fa4b8baadf9db299cb6ac87c96a8977dbe",
|
"reference": "1631040ea8fc5e0e405c00d35cbf2c0b7b555f64",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -2622,7 +2987,7 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"framework"
|
"framework"
|
||||||
],
|
],
|
||||||
"time": "2017-03-10T18:35:48+00:00"
|
"time": "2017-04-05T12:52:29+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "twig/twig",
|
"name": "twig/twig",
|
||||||
@ -2690,49 +3055,59 @@
|
|||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
{
|
{
|
||||||
"name": "friendsofphp/php-cs-fixer",
|
"name": "friendsofphp/php-cs-fixer",
|
||||||
"version": "v2.1.2",
|
"version": "v2.2.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
|
"url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
|
||||||
"reference": "c7de769d7b44f2c9de68e1f678b65efd8126f60b"
|
"reference": "d6f17423412d33df6b69c9aaf12037b91703533b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/c7de769d7b44f2c9de68e1f678b65efd8126f60b",
|
"url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/d6f17423412d33df6b69c9aaf12037b91703533b",
|
||||||
"reference": "c7de769d7b44f2c9de68e1f678b65efd8126f60b",
|
"reference": "d6f17423412d33df6b69c9aaf12037b91703533b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
"doctrine/annotations": "^1.2",
|
||||||
"ext-tokenizer": "*",
|
"ext-tokenizer": "*",
|
||||||
"php": "^5.3.6 || >=7.0 <7.2",
|
"php": "^5.3.6 || >=7.0 <7.2",
|
||||||
"sebastian/diff": "^1.1",
|
"sebastian/diff": "^1.1",
|
||||||
"symfony/console": "^2.3 || ^3.0",
|
"symfony/console": "^2.4 || ^3.0",
|
||||||
"symfony/event-dispatcher": "^2.1 || ^3.0",
|
"symfony/event-dispatcher": "^2.1 || ^3.0",
|
||||||
"symfony/filesystem": "^2.4 || ^3.0",
|
"symfony/filesystem": "^2.4 || ^3.0",
|
||||||
"symfony/finder": "^2.2 || ^3.0",
|
"symfony/finder": "^2.2 || ^3.0",
|
||||||
|
"symfony/options-resolver": "^2.6 || ^3.0",
|
||||||
"symfony/polyfill-php54": "^1.0",
|
"symfony/polyfill-php54": "^1.0",
|
||||||
"symfony/polyfill-php55": "^1.3",
|
"symfony/polyfill-php55": "^1.3",
|
||||||
|
"symfony/polyfill-php70": "^1.0",
|
||||||
"symfony/polyfill-xml": "^1.3",
|
"symfony/polyfill-xml": "^1.3",
|
||||||
"symfony/process": "^2.3 || ^3.0",
|
"symfony/process": "^2.3 || ^3.0",
|
||||||
"symfony/stopwatch": "^2.5 || ^3.0"
|
"symfony/stopwatch": "^2.5 || ^3.0"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"hhvm": "<3.9"
|
"hhvm": "<3.18"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"gecko-packages/gecko-php-unit": "^2.0",
|
"gecko-packages/gecko-php-unit": "^2.0",
|
||||||
"justinrainbow/json-schema": "^5.0",
|
"justinrainbow/json-schema": "^5.0",
|
||||||
"phpunit/phpunit": "^4.5 || ^5.0",
|
"phpunit/phpunit": "^4.5 || ^5.0",
|
||||||
"satooshi/php-coveralls": "^1.0",
|
"satooshi/php-coveralls": "^1.0",
|
||||||
"symfony/phpunit-bridge": "^3.2"
|
"symfony/phpunit-bridge": "^3.2.2"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-xml": "For better performance."
|
"ext-mbstring": "For handling non-UTF8 characters in cache signature.",
|
||||||
|
"ext-xml": "For better performance.",
|
||||||
|
"symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible."
|
||||||
},
|
},
|
||||||
"bin": [
|
"bin": [
|
||||||
"php-cs-fixer"
|
"php-cs-fixer"
|
||||||
],
|
],
|
||||||
"type": "application",
|
"type": "application",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "2.2-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"PhpCsFixer\\": "src/"
|
"PhpCsFixer\\": "src/"
|
||||||
@ -2753,7 +3128,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "A tool to automatically fix PHP code style",
|
"description": "A tool to automatically fix PHP code style",
|
||||||
"time": "2017-03-15T17:13:07+00:00"
|
"time": "2017-03-31T16:16:30+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ircmaxell/password-compat",
|
"name": "ircmaxell/password-compat",
|
||||||
@ -2905,7 +3280,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/phpunit-bridge",
|
"name": "symfony/phpunit-bridge",
|
||||||
"version": "v3.2.6",
|
"version": "v3.2.7",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/phpunit-bridge.git",
|
"url": "https://github.com/symfony/phpunit-bridge.git",
|
||||||
|
23
gulpfile.js
23
gulpfile.js
@ -4,6 +4,7 @@ var gulp = require('gulp'),
|
|||||||
gulp.task('css', function() {
|
gulp.task('css', function() {
|
||||||
return gulp.src([
|
return gulp.src([
|
||||||
'node_modules/semantic-ui/dist/semantic.css',
|
'node_modules/semantic-ui/dist/semantic.css',
|
||||||
|
'node_modules/lightbox2/dist/css/lightbox.css',
|
||||||
'app/Resources/assets/style/style.scss',
|
'app/Resources/assets/style/style.scss',
|
||||||
])
|
])
|
||||||
.pipe(plugins.sass().on('error', plugins.sass.logError))
|
.pipe(plugins.sass().on('error', plugins.sass.logError))
|
||||||
@ -31,23 +32,35 @@ gulp.task('js', function() {
|
|||||||
return gulp.src([
|
return gulp.src([
|
||||||
'node_modules/jquery/dist/jquery.js',
|
'node_modules/jquery/dist/jquery.js',
|
||||||
'node_modules/semantic-ui/dist/semantic.js',
|
'node_modules/semantic-ui/dist/semantic.js',
|
||||||
|
'node_modules/lightbox2/dist/js/lightbox.js',
|
||||||
'app/Resources/assets/js/**.js',
|
'app/Resources/assets/js/**.js',
|
||||||
|
'node_modules/three/examples/js/libs/stats.min.js'
|
||||||
])
|
])
|
||||||
.pipe(plugins.concat('main.js'))
|
.pipe(plugins.concat('main.js'))
|
||||||
.pipe(gulp.dest('web/resources/js'));
|
.pipe(gulp.dest('web/resources/js'));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('files', function () {
|
gulp.task('files:semantic', function () {
|
||||||
return gulp.src('node_modules/semantic-ui/dist/themes/**')
|
return gulp.src(
|
||||||
.pipe(plugins.newer('web/resources/css/themes'))
|
'node_modules/semantic-ui/dist/themes/**'
|
||||||
|
)
|
||||||
.pipe(gulp.dest('web/resources/css/themes'));
|
.pipe(gulp.dest('web/resources/css/themes'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
gulp.task('files:images', function () {
|
||||||
|
return gulp.src([
|
||||||
|
'node_modules/lightbox2/dist/images/**',
|
||||||
|
'app/Resources/assets/images/**'
|
||||||
|
])
|
||||||
|
.pipe(gulp.dest('web/resources/images'));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
gulp.task('watch', ['js', 'css', 'three'], function () {
|
gulp.task('watch', ['js', 'css', 'three'], function () {
|
||||||
gulp.watch('app/Resources/assets/js/**.js' , ['js']);
|
gulp.watch('app/Resources/assets/js/**.js' , ['js']);
|
||||||
gulp.watch('app/Resources/assets/style/**/*.sass' , ['css']);
|
gulp.watch('app/Resources/assets/style/**/*.scss' , ['css']);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('default', function () {
|
gulp.task('default', function () {
|
||||||
return gulp.start(['files', 'js', 'css', 'three']);
|
return gulp.start(['files:semantic', 'files:images', 'js', 'css', 'three']);
|
||||||
});
|
});
|
@ -11,6 +11,7 @@
|
|||||||
"gulp-sass": "^2.3.2",
|
"gulp-sass": "^2.3.2",
|
||||||
"gulp-watch": "^4.3.11",
|
"gulp-watch": "^4.3.11",
|
||||||
"jquery": "^3.2.1",
|
"jquery": "^3.2.1",
|
||||||
|
"lightbox2": "^2.9.0",
|
||||||
"semantic-ui": "^2.2.9",
|
"semantic-ui": "^2.2.9",
|
||||||
"three": "^0.84.0"
|
"three": "^0.84.0"
|
||||||
},
|
},
|
||||||
|
@ -13,7 +13,6 @@ 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;
|
||||||
use AppBundle\Api\Exception\EmptyResponseException;
|
use AppBundle\Api\Exception\EmptyResponseException;
|
||||||
use Symfony\Component\Asset\Exception\LogicException;
|
|
||||||
use Symfony\Component\Debug\Exception\ContextErrorException;
|
use Symfony\Component\Debug\Exception\ContextErrorException;
|
||||||
|
|
||||||
class Brickset extends \SoapClient
|
class Brickset extends \SoapClient
|
||||||
@ -47,6 +46,7 @@ class Brickset extends \SoapClient
|
|||||||
$this->apiKey = $apikey;
|
$this->apiKey = $apikey;
|
||||||
|
|
||||||
$options['cache_wsdl'] = WSDL_CACHE_NONE;
|
$options['cache_wsdl'] = WSDL_CACHE_NONE;
|
||||||
|
$options['exceptions'] = true;
|
||||||
|
|
||||||
foreach (self::$classmap as $key => $value) {
|
foreach (self::$classmap as $key => $value) {
|
||||||
if (!isset($options['classmap'][$key])) {
|
if (!isset($options['classmap'][$key])) {
|
||||||
@ -56,7 +56,12 @@ class Brickset extends \SoapClient
|
|||||||
if (!$wsdl) {
|
if (!$wsdl) {
|
||||||
$wsdl = self::WSDL;
|
$wsdl = self::WSDL;
|
||||||
}
|
}
|
||||||
parent::__construct($wsdl, $options);
|
|
||||||
|
try {
|
||||||
|
parent::__construct($wsdl, $options);
|
||||||
|
} catch (\Exception $exception) {
|
||||||
|
throw new ApiException(ApiException::BRICKSET);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,11 +78,14 @@ class Brickset extends \SoapClient
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$this->checkApiKey();
|
$this->checkApiKey();
|
||||||
|
|
||||||
return $this->__soapCall($method, [$parameters])->{$method.'Result'};
|
return $this->__soapCall($method, [$parameters])->{$method.'Result'};
|
||||||
} catch (\SoapFault $e) {
|
} catch (\SoapFault $e) {
|
||||||
throw new CallFailedException(ApiException::BRICKSET);
|
throw new CallFailedException(ApiException::BRICKSET);
|
||||||
} catch (ContextErrorException $e) {
|
} catch (ContextErrorException $e) {
|
||||||
throw new EmptyResponseException(ApiException::BRICKSET);
|
throw new EmptyResponseException(ApiException::BRICKSET);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
throw new ApiException(ApiException::BRICKSET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +113,7 @@ class Brickset extends \SoapClient
|
|||||||
|
|
||||||
$response = $this->call('getSets', $parameters)->sets;
|
$response = $this->call('getSets', $parameters)->sets;
|
||||||
|
|
||||||
return is_array($response) ? $response : [$response];
|
return is_array($response) ? $response : [$this->getSet($response->getSetID())];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -258,7 +266,7 @@ class Brickset extends \SoapClient
|
|||||||
{
|
{
|
||||||
$parameters['apiKey'] = $this->apiKey;
|
$parameters['apiKey'] = $this->apiKey;
|
||||||
|
|
||||||
if($this->__soapCall('checkKey', [$parameters])->checkKeyResult != 'OK') {
|
if ($this->__soapCall('checkKey', [$parameters])->checkKeyResult != 'OK') {
|
||||||
throw new AuthenticationFailedException(ApiException::BRICKSET);
|
throw new AuthenticationFailedException(ApiException::BRICKSET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ use AppBundle\Api\Exception\EmptyResponseException;
|
|||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
use GuzzleHttp\Exception\ClientException;
|
use GuzzleHttp\Exception\ClientException;
|
||||||
use GuzzleHttp\Exception\ConnectException;
|
use GuzzleHttp\Exception\ConnectException;
|
||||||
use Symfony\Component\Asset\Exception\LogicException;
|
|
||||||
|
|
||||||
class Rebrickable_v3
|
class Rebrickable_v3
|
||||||
{
|
{
|
||||||
@ -59,11 +58,11 @@ class Rebrickable_v3
|
|||||||
} catch (ClientException $e) {
|
} catch (ClientException $e) {
|
||||||
if ($e->getCode() == 404) {
|
if ($e->getCode() == 404) {
|
||||||
throw new EmptyResponseException(ApiException::REBRICKABLE);
|
throw new EmptyResponseException(ApiException::REBRICKABLE);
|
||||||
} else if ($e->getCode() == 401) {
|
} elseif ($e->getCode() == 401) {
|
||||||
throw new AuthenticationFailedException(ApiException::REBRICKABLE);
|
throw new AuthenticationFailedException(ApiException::REBRICKABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ApiException(ApiException::REBRICKABLE,$e,$e->getCode());
|
throw new ApiException(ApiException::REBRICKABLE, $e, $e->getCode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,4 +47,19 @@ class BricksetManager
|
|||||||
|
|
||||||
return isset($sets[0]) ? $sets[0] : null;
|
return isset($sets[0]) ? $sets[0] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSetInstructions($id)
|
||||||
|
{
|
||||||
|
return $this->bricksetClient->getInstructions($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSetReviews($id)
|
||||||
|
{
|
||||||
|
return $this->bricksetClient->getReviews($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAdditionalImages($id)
|
||||||
|
{
|
||||||
|
return $this->bricksetClient->getAdditionalImages($id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,18 +119,19 @@ class RebrickableManager
|
|||||||
return $this->serializer->deserialize($data, PartCategory::class, self::FORMAT);
|
return $this->serializer->deserialize($data, PartCategory::class, self::FORMAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPartsByLDrawNumber($number) {
|
public function getPartsByLDrawNumber($number)
|
||||||
|
{
|
||||||
$options = [
|
$options = [
|
||||||
'query' => [
|
'query' => [
|
||||||
'ldraw_id' => $number
|
'ldraw_id' => $number,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
$response = $this->rebrickableClient->call('GET','lego/parts', $options);
|
$response = $this->rebrickableClient->call('GET', 'lego/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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace AppBundle\Command;
|
|
||||||
|
|
||||||
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
|
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
|
||||||
|
|
||||||
class LoadLDRawLibraryCommand extends ContainerAwareCommand
|
|
||||||
{
|
|
||||||
protected function configure()
|
|
||||||
{
|
|
||||||
$this
|
|
||||||
->setName('app:load:ldraw')
|
|
||||||
->setDescription('Loads LDraw library parts')
|
|
||||||
->setHelp('This command allows you to..')
|
|
||||||
->addArgument('ldraw_path', InputArgument::OPTIONAL, 'Path to LDraw library folder');
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
|
||||||
{
|
|
||||||
$ldrawLoader = $this->getContainer()->get('service.loader.ldraw');
|
|
||||||
$ldrawLoader->setOutput($output);
|
|
||||||
|
|
||||||
//TODO log errors
|
|
||||||
|
|
||||||
try {
|
|
||||||
// TODO handle relative path to dir
|
|
||||||
if (($ldrawPath = $input->getArgument('ldraw_path')) == null) {
|
|
||||||
$ldrawPath = $ldrawLoader->downloadLibrary();
|
|
||||||
}
|
|
||||||
|
|
||||||
$ldrawLoader->loadData($ldrawPath);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
printf($e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
89
src/AppBundle/Command/LoadModelsCommand.php
Normal file
89
src/AppBundle/Command/LoadModelsCommand.php
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Command;
|
||||||
|
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
|
||||||
|
use Symfony\Component\Console\Command\LockableTrait;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputDefinition;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
class LoadModelsCommand extends ContainerAwareCommand
|
||||||
|
{
|
||||||
|
use LockableTrait;
|
||||||
|
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this
|
||||||
|
->setName('app:load:models')
|
||||||
|
->setDescription('Loads LDraw library models into database')
|
||||||
|
->setHelp('This command allows you to load LDraw library models into database while converting .dat files to .stl format.')
|
||||||
|
->setDefinition(
|
||||||
|
new InputDefinition([
|
||||||
|
new InputArgument('ldraw', InputArgument::REQUIRED, 'Path to LDraw library directory'),
|
||||||
|
// new InputOption('images', 'i', InputOption::VALUE_NONE, 'Do you want to generate images of models?'),
|
||||||
|
new InputOption('all', 'a', InputOption::VALUE_NONE, 'Load all models from LDraw libary folder (/parts directory)'),
|
||||||
|
new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'Load single modle into database'),
|
||||||
|
new InputOption('update', 'u', InputOption::VALUE_NONE, 'Overwrite already loaded models'),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
if (!$this->lock()) {
|
||||||
|
$output->writeln('The command is already running in another process.');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$modelLoader = $this->getContainer()->get('service.loader.model');
|
||||||
|
$modelLoader->setOutput($output);
|
||||||
|
$modelLoader->setRewite($input->getOption('update'));
|
||||||
|
|
||||||
|
$ldraw = $input->getArgument('ldraw');
|
||||||
|
|
||||||
|
if ($ldrawPath = realpath($ldraw)) {
|
||||||
|
$modelLoader->setLDrawLibraryContext($ldrawPath);
|
||||||
|
|
||||||
|
if (($path = $input->getOption('file')) != null) {
|
||||||
|
if ($file = realpath($path)) {
|
||||||
|
$output->writeln([
|
||||||
|
'Loading model',
|
||||||
|
'path: '.$file,
|
||||||
|
'------------------------------------------------------------------------------',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$modelLoader->loadOneModel($file);
|
||||||
|
|
||||||
|
$errorCount = $this->getContainer()->get('monolog.logger.loader')->countErrors();
|
||||||
|
$errors = $errorCount ? '<error>'.$errorCount.'</error>' : '<info>0</info>';
|
||||||
|
|
||||||
|
$output->writeln(['Done with "'.$errors.'" errors.']);
|
||||||
|
} else {
|
||||||
|
$output->writeln("File $path not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load all models inside ldraw/parts directory
|
||||||
|
if ($input->getOption('all')) {
|
||||||
|
$output->writeln([
|
||||||
|
'Loading models from LDraw library: <comment>'.$ldrawPath.'</comment>',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$modelLoader->loadAllModels();
|
||||||
|
|
||||||
|
$errorCount = $this->getContainer()->get('monolog.logger.loader')->countErrors();
|
||||||
|
$errors = $errorCount ? '<error>'.$errorCount.'</error>' : '<info>0</info>';
|
||||||
|
|
||||||
|
$output->writeln(['Done with "'.$errors.'" errors.']);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$output->writeln($ldraw.' is not valid path');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->release();
|
||||||
|
}
|
||||||
|
}
|
@ -12,8 +12,8 @@ class LoadRebrickableDataCommand extends ContainerAwareCommand
|
|||||||
{
|
{
|
||||||
$this
|
$this
|
||||||
->setName('app:load:rebrickable')
|
->setName('app:load:rebrickable')
|
||||||
->setDescription('Loads Rebrickable database')
|
->setDescription('Loads Rebrickable data about sets and parts into database.')
|
||||||
->setHelp('This command allows you to..');
|
->setHelp('This command allows you to load Rebrickable CSV files containing information about sets and parts into database.');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
@ -12,8 +12,8 @@ class LoadRelationCommand extends ContainerAwareCommand
|
|||||||
{
|
{
|
||||||
$this
|
$this
|
||||||
->setName('app:load:relations')
|
->setName('app:load:relations')
|
||||||
->setDescription('Loads relations between LDraw models and Rebrickable parts')
|
->setDescription('Loads relations between LDraw models and Rebrickable parts.')
|
||||||
->setHelp('This command allows you to..');
|
->setHelp('This command allows you to load relation between models and parts into database.');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace AppBundle\Controller\Rebrickable;
|
namespace AppBundle\Controller\Brickset;
|
||||||
|
|
||||||
use AppBundle\Entity\Rebrickable\Color;
|
use AppBundle\Api\Exception\EmptyResponseException;
|
||||||
use AppBundle\Entity\Rebrickable\Inventory_Part;
|
|
||||||
use AppBundle\Entity\Rebrickable\Part;
|
|
||||||
use AppBundle\Entity\Rebrickable\Set;
|
use AppBundle\Entity\Rebrickable\Set;
|
||||||
use AppBundle\Entity\Rebrickable\Theme;
|
use AppBundle\Entity\Rebrickable\Theme;
|
||||||
use AppBundle\Form\FilterSetType;
|
use AppBundle\Form\FilterSetType;
|
||||||
@ -13,12 +11,12 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
|||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/brickset")
|
* @Route("/brickset/sets")
|
||||||
*/
|
*/
|
||||||
class SetController extends Controller
|
class SetController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @Route("/", name="set_browse")
|
* @Route("/", name="brickset_browse")
|
||||||
*/
|
*/
|
||||||
public function browseAction(Request $request)
|
public function browseAction(Request $request)
|
||||||
{
|
{
|
||||||
@ -30,11 +28,17 @@ class SetController extends Controller
|
|||||||
if ($form->isSubmitted() && $form->isValid()) {
|
if ($form->isSubmitted() && $form->isValid()) {
|
||||||
$data = $form->getData();
|
$data = $form->getData();
|
||||||
|
|
||||||
$sets = $this->get('api.client.brickset')->getSets([
|
try {
|
||||||
'theme' => $data['theme'] ? $data['theme']->getTheme() : '',
|
$sets = $this->get('api.client.brickset')->getSets([
|
||||||
'subtheme' => $data['subtheme'] ? $data['subtheme']->getSubtheme() : '',
|
'theme' => $data['theme'] ? $data['theme']->getTheme() : '',
|
||||||
'year' => $data['years'] ? $data['years']->getYear() : '',
|
'subtheme' => $data['subtheme'] ? $data['subtheme']->getSubtheme() : '',
|
||||||
]);
|
'year' => $data['years'] ? $data['years']->getYear() : '',
|
||||||
|
]);
|
||||||
|
} catch (EmptyResponseException $e) {
|
||||||
|
$this->addFlash('warning', 'No set found on '.$e->getService());
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->addFlash('error', $e->getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->render('brickset/browse.html.twig', [
|
return $this->render('brickset/browse.html.twig', [
|
||||||
@ -42,4 +46,61 @@ class SetController extends Controller
|
|||||||
'sets' => $sets,
|
'sets' => $sets,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/{id}/instructions", name="brickset_instructions")
|
||||||
|
*/
|
||||||
|
public function instructionsAction(Request $request, $id)
|
||||||
|
{
|
||||||
|
$instructions = [];
|
||||||
|
try {
|
||||||
|
$instructions = $this->get('api.manager.brickset')->getSetInstructions($id);
|
||||||
|
} catch (EmptyResponseException $e) {
|
||||||
|
// $this->addFlash('warning', 'No instruction found on Brickset.com');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->addFlash('error', $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->render('brickset/instructions.html.twig', [
|
||||||
|
'instructions' => $instructions,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/{id}/reviews", name="brickset_reviews")
|
||||||
|
*/
|
||||||
|
public function reviewsAction(Request $request, $id)
|
||||||
|
{
|
||||||
|
$reviews = [];
|
||||||
|
try {
|
||||||
|
$reviews = $this->get('api.manager.brickset')->getSetReviews($id);
|
||||||
|
} catch (EmptyResponseException $e) {
|
||||||
|
// $this->addFlash('warning', 'No review found on Brickset.com');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->addFlash('error', $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->render('brickset/reviews.html.twig', [
|
||||||
|
'reviews' => $reviews,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/{id}/images", name="brickset_images")
|
||||||
|
*/
|
||||||
|
public function imagesAction(Request $request, $id)
|
||||||
|
{
|
||||||
|
$images = [];
|
||||||
|
try {
|
||||||
|
$images = $this->get('api.manager.brickset')->getAdditionalImages($id);
|
||||||
|
} catch (EmptyResponseException $e) {
|
||||||
|
// $this->addFlash('warning', 'No images found on Brickset.com');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->addFlash('error', $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->render('brickset/images.html.twig', [
|
||||||
|
'images' => $images,
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace AppBundle\Controller;
|
namespace AppBundle\Controller;
|
||||||
|
|
||||||
use AppBundle\Entity\LDraw\Model;
|
|
||||||
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;
|
||||||
@ -11,59 +10,33 @@ use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
|||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/media")
|
* @Route("/files")
|
||||||
*/
|
*/
|
||||||
class MediaController extends Controller
|
class MediaController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @Route("/model/stl/{number}", name="model_stl")
|
* @Route("/{path}", name="media_file", requirements={"path"=".+"})
|
||||||
*
|
*
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function stlAction(Model $model)
|
public function stlAction($path)
|
||||||
{
|
{
|
||||||
$mediaFilesystem = $this->get('oneup_flysystem.media_filesystem');
|
$mediaFilesystem = $this->get('oneup_flysystem.media_filesystem');
|
||||||
|
|
||||||
if ($mediaFilesystem->has($model->getPath())) {
|
if ($mediaFilesystem->has($path)) {
|
||||||
$response = new BinaryFileResponse($mediaFilesystem->getAdapter()->getPathPrefix().DIRECTORY_SEPARATOR.$model->getPath());
|
$response = new BinaryFileResponse($mediaFilesystem->getAdapter()->getPathPrefix().DIRECTORY_SEPARATOR.$path);
|
||||||
$response->headers->set('Content-Type', 'application/vnd.ms-pki.stl');
|
$response->headers->set('Content-Type', $mediaFilesystem->getMimetype($path));
|
||||||
|
|
||||||
// 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,
|
||||||
$model->getNumber().'.stl'
|
basename($path)
|
||||||
);
|
);
|
||||||
|
|
||||||
$response->headers->set('Content-Disposition', $disposition);
|
$response->headers->set('Content-Disposition', $disposition);
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
throw new FileNotFoundException($model->getPath());
|
throw new FileNotFoundException($path);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Route("/model/image/{number}", name="model_image")
|
|
||||||
*
|
|
||||||
* @return Response
|
|
||||||
*/
|
|
||||||
public function imageAction(Model $model)
|
|
||||||
{
|
|
||||||
$mediaFilesystem = $this->get('oneup_flysystem.media_filesystem');
|
|
||||||
|
|
||||||
if ($mediaFilesystem->has('ldraw'.DIRECTORY_SEPARATOR.'images'.DIRECTORY_SEPARATOR.$model->getNumber().'.png')) {
|
|
||||||
$response = new BinaryFileResponse($mediaFilesystem->getAdapter()->getPathPrefix().DIRECTORY_SEPARATOR.'ldraw'.DIRECTORY_SEPARATOR.'images'.DIRECTORY_SEPARATOR.$model->getNumber().'.png');
|
|
||||||
$response->headers->set('Content-Type', 'image/png');
|
|
||||||
|
|
||||||
// Create the disposition of the file
|
|
||||||
$disposition = $response->headers->makeDisposition(
|
|
||||||
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
|
|
||||||
$model->getNumber().'png'
|
|
||||||
);
|
|
||||||
|
|
||||||
$response->headers->set('Content-Disposition', $disposition);
|
|
||||||
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
throw new FileNotFoundException($model->getNumber().'png');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace AppBundle\Controller\LDraw;
|
namespace AppBundle\Controller;
|
||||||
|
|
||||||
use AppBundle\Entity\LDraw\Model;
|
use AppBundle\Entity\LDraw\Model;
|
||||||
use AppBundle\Entity\Rebrickable\Part;
|
use AppBundle\Entity\Rebrickable\Part;
|
||||||
use AppBundle\Entity\Rebrickable\Set;
|
use AppBundle\Entity\Rebrickable\Set;
|
||||||
use AppBundle\Form\Filter\ModelFilterType;
|
use AppBundle\Form\Filter\Model\ModelFilterType;
|
||||||
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;
|
||||||
@ -14,24 +14,21 @@ use Symfony\Component\HttpFoundation\Request;
|
|||||||
/**
|
/**
|
||||||
* Part controller.
|
* Part controller.
|
||||||
*
|
*
|
||||||
* @Route("ldraw")
|
* @Route("models")
|
||||||
*/
|
*/
|
||||||
class ModelController extends Controller
|
class ModelController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Lists all part entities.
|
* Lists all part entities.
|
||||||
*
|
*
|
||||||
* @Route("/models/", name="ldraw_model_index")
|
* @Route("/", name="model_index")
|
||||||
* @Method("GET")
|
* @Method("GET")
|
||||||
*/
|
*/
|
||||||
public function indexAction(Request $request)
|
public function indexAction(Request $request)
|
||||||
{
|
{
|
||||||
$em = $this->getDoctrine()->getManager();
|
|
||||||
|
|
||||||
$form = $this->get('form.factory')->create(ModelFilterType::class);
|
$form = $this->get('form.factory')->create(ModelFilterType::class);
|
||||||
|
|
||||||
$filterBuilder = $this->get('repository.ldraw.model')
|
$filterBuilder = $this->get('repository.ldraw.model')->getFilteredQueryBuilder();
|
||||||
->createQueryBuilder('model');
|
|
||||||
|
|
||||||
if ($request->query->has($form->getName())) {
|
if ($request->query->has($form->getName())) {
|
||||||
// manually bind values from the request
|
// manually bind values from the request
|
||||||
@ -45,10 +42,10 @@ class ModelController extends Controller
|
|||||||
$models = $paginator->paginate(
|
$models = $paginator->paginate(
|
||||||
$filterBuilder->getQuery(),
|
$filterBuilder->getQuery(),
|
||||||
$request->query->getInt('page', 1)/*page number*/,
|
$request->query->getInt('page', 1)/*page number*/,
|
||||||
$request->query->getInt('limit', 100)/*limit per page*/
|
$request->query->getInt('limit', 40)/*limit per page*/
|
||||||
);
|
);
|
||||||
|
|
||||||
return $this->render('ldraw/model/index.html.twig', [
|
return $this->render('model/index.html.twig', [
|
||||||
'models' => $models,
|
'models' => $models,
|
||||||
'form' => $form->createView(),
|
'form' => $form->createView(),
|
||||||
]);
|
]);
|
||||||
@ -57,27 +54,29 @@ class ModelController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Finds and displays a part entity.
|
* Finds and displays a part entity.
|
||||||
*
|
*
|
||||||
* @Route("/models/{number}", name="model_detail")
|
* @Route("/{number}", name="model_detail")
|
||||||
* @Method("GET")
|
* @Method("GET")
|
||||||
*/
|
*/
|
||||||
public function detailAction($number)
|
public function detailAction($number)
|
||||||
{
|
{
|
||||||
$em = $this->getDoctrine()->getManager();
|
$em = $this->getDoctrine()->getManager();
|
||||||
|
|
||||||
if($model = $this->get('manager.ldraw.model')->findByNumber($number)) {
|
if ($model = $this->get('repository.ldraw.model')->findOneByNumber($number)) {
|
||||||
try {
|
try {
|
||||||
$rbParts = $model != null ? $em->getRepository(Part::class)->findAllByModel($model) : null;
|
$rbParts = $model != null ? $em->getRepository(Part::class)->findAllByModel($model) : null;
|
||||||
$sets = $model != null ? $em->getRepository(Set::class)->findAllByModel($model) : null;
|
$sets = $model != null ? $em->getRepository(Set::class)->findAllByModel($model) : null;
|
||||||
|
|
||||||
return $this->render('ldraw/model/detail.html.twig', [
|
$related = $em->getRepository(Model::class)->findAllRelatedModels($model->getNumber());
|
||||||
|
|
||||||
|
return $this->render('model/detail.html.twig', [
|
||||||
'model' => $model,
|
'model' => $model,
|
||||||
'rbParts' => $rbParts,
|
'rbParts' => $rbParts,
|
||||||
'sets' => $sets,
|
'sets' => $sets,
|
||||||
|
'related' => $related,
|
||||||
]);
|
]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->addFlash('error', $e->getMessage());
|
$this->addFlash('error', $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->render('error/error.html.twig');
|
return $this->render('error/error.html.twig');
|
@ -3,8 +3,8 @@
|
|||||||
namespace AppBundle\Controller\Rebrickable;
|
namespace AppBundle\Controller\Rebrickable;
|
||||||
|
|
||||||
use AppBundle\Entity\Rebrickable\Color;
|
use AppBundle\Entity\Rebrickable\Color;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
|
||||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Part controller.
|
* Part controller.
|
||||||
@ -14,10 +14,10 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
|||||||
class ColorController extends Controller
|
class ColorController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @Route("/", name="color_index")
|
* @Route("/", name="color_index")
|
||||||
*/
|
*/
|
||||||
public function indexAction() {
|
public function indexAction()
|
||||||
|
{
|
||||||
$em = $this->getDoctrine()->getManager();
|
$em = $this->getDoctrine()->getManager();
|
||||||
|
|
||||||
$colors = $em->getRepository(Color::class)->findAll();
|
$colors = $em->getRepository(Color::class)->findAll();
|
||||||
@ -26,4 +26,4 @@ class ColorController extends Controller
|
|||||||
'colors' => $colors,
|
'colors' => $colors,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,13 @@
|
|||||||
namespace AppBundle\Controller\Rebrickable;
|
namespace AppBundle\Controller\Rebrickable;
|
||||||
|
|
||||||
use AppBundle\Api\Exception\EmptyResponseException;
|
use AppBundle\Api\Exception\EmptyResponseException;
|
||||||
|
use AppBundle\Entity\Rebrickable\Category;
|
||||||
use AppBundle\Entity\Rebrickable\Part;
|
use AppBundle\Entity\Rebrickable\Part;
|
||||||
use AppBundle\Entity\Rebrickable\Set;
|
use AppBundle\Entity\Rebrickable\Set;
|
||||||
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\HttpFoundation\Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Part controller.
|
* Part controller.
|
||||||
@ -16,19 +18,41 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
|||||||
*/
|
*/
|
||||||
class PartController extends Controller
|
class PartController extends Controller
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @Route("/", name="part_index")
|
||||||
|
*/
|
||||||
|
public function indexAction(Request $request)
|
||||||
|
{
|
||||||
|
$em = $this->getDoctrine()->getManager();
|
||||||
|
|
||||||
|
$queryBuilder = $em->getRepository(Part::class)->createQueryBuilder('part');
|
||||||
|
$queryBuilder->where('part.category = 17');
|
||||||
|
|
||||||
|
$paginator = $this->get('knp_paginator');
|
||||||
|
$sets = $paginator->paginate(
|
||||||
|
$queryBuilder->getQuery(),
|
||||||
|
$request->query->getInt('page', 1)/*page number*/,
|
||||||
|
$request->query->getInt('limit', 30)/*limit per page*/
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->render(':rebrickable/part:index.html.twig', [
|
||||||
|
'parts' => $sets,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds and displays a part entity.
|
* Finds and displays a part entity.
|
||||||
*
|
*
|
||||||
* @Route("/{number}", name="rebrickable_part_show")
|
* @Route("/{number}", name="reb_part_detail")
|
||||||
* @Method("GET")
|
* @Method("GET")
|
||||||
*/
|
*/
|
||||||
public function showAction(Part $part = null)
|
public function detailAction(Part $part)
|
||||||
{
|
{
|
||||||
$em = $this->getDoctrine()->getManager();
|
$em = $this->getDoctrine()->getManager();
|
||||||
|
|
||||||
$apiPart = null;
|
$apiPart = null;
|
||||||
|
|
||||||
if($part) {
|
if ($part) {
|
||||||
try {
|
try {
|
||||||
$apiPart = $this->get('api.manager.rebrickable')->getPart($part->getNumber());
|
$apiPart = $this->get('api.manager.rebrickable')->getPart($part->getNumber());
|
||||||
} catch (EmptyResponseException $e) {
|
} catch (EmptyResponseException $e) {
|
||||||
|
@ -2,17 +2,13 @@
|
|||||||
|
|
||||||
namespace AppBundle\Controller\Rebrickable;
|
namespace AppBundle\Controller\Rebrickable;
|
||||||
|
|
||||||
use AppBundle\Api\Exception\EmptyResponseException;
|
|
||||||
use AppBundle\Entity\LDraw\Model;
|
|
||||||
use AppBundle\Entity\Rebrickable\Color;
|
use AppBundle\Entity\Rebrickable\Color;
|
||||||
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\Part;
|
||||||
use AppBundle\Entity\Rebrickable\Set;
|
use AppBundle\Entity\Rebrickable\Set;
|
||||||
use AppBundle\Entity\Rebrickable\Theme;
|
|
||||||
use AppBundle\Form\FilterSetType;
|
|
||||||
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;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,87 +17,46 @@ use Symfony\Component\HttpFoundation\Response;
|
|||||||
class SetController extends Controller
|
class SetController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @Route("/", name="set_index")
|
* @Route("/{number}/parts", name="rebrickable_set_parts")
|
||||||
*/
|
*/
|
||||||
public function indexAction(Request $request)
|
public function partsAction(Set $set)
|
||||||
{
|
{
|
||||||
$em = $this->getDoctrine()->getManager();
|
$em = $this->getDoctrine()->getManager();
|
||||||
|
|
||||||
$qb = $em->getRepository(Set::class)->createQueryBuilder('s');
|
|
||||||
|
|
||||||
$paginator = $this->get('knp_paginator');
|
|
||||||
$sets = $paginator->paginate(
|
|
||||||
$qb->getQuery(),
|
|
||||||
$request->query->getInt('page', 1)/*page number*/,
|
|
||||||
$request->query->getInt('limit', 30)/*limit per page*/
|
|
||||||
);
|
|
||||||
|
|
||||||
return $this->render('rebrickable/set/index.html.twig', [
|
|
||||||
'sets' => $sets,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Route("/detail/{number}_{name}", name="set_detail")
|
|
||||||
*/
|
|
||||||
public function detailAction(Request $request, $number, $name = null)
|
|
||||||
{
|
|
||||||
$brset = null;
|
|
||||||
try {
|
|
||||||
$brset = $this->get('api.manager.brickset')->getSetByNumber($number);
|
|
||||||
} catch (EmptyResponseException $e) {
|
|
||||||
$this->addFlash('warning', 'Set not found in Brickset database');
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
$this->addFlash('error', $e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
$set = $this->getDoctrine()->getManager()->getRepository(Set::class)->find($number);
|
|
||||||
|
|
||||||
$rbset = $this->get('api.manager.rebrickable')->getSet($number);
|
|
||||||
|
|
||||||
$em = $this->getDoctrine()->getManager();
|
|
||||||
$em->getRepository(Color::class)->findAll();
|
$em->getRepository(Color::class)->findAll();
|
||||||
$em->getRepository(Theme::class)->findAll();
|
$em->getRepository(Part::class)->findAllBySetNumber($set->getNumber());
|
||||||
|
|
||||||
return $this->render('rebrickable/set/detail.html.twig', [
|
$regularParts = $em->getRepository(Inventory_Part::class)->findAllRegularBySetNumber($set->getNumber());
|
||||||
'set' => $set,
|
$spareParts = $em->getRepository(Inventory_Part::class)->findAllSpareBySetNumber($set->getNumber());
|
||||||
'brset' => $brset,
|
|
||||||
'rbset' => $rbset,
|
$template = $this->render('rebrickable/set/parts.html.twig', [
|
||||||
'parts' => $em->getRepository(Model::class)->findAllBySetNumber($number),
|
'regularParts' => $regularParts,
|
||||||
'inventoryParts' => $em->getRepository(Inventory_Part::class)->findAllBySetNumber($number),
|
'spareParts' => $spareParts,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$json = json_encode($template->getContent());
|
||||||
|
$response = new Response($json, 200);
|
||||||
|
$response->headers->set('Content-Type', 'application/json');
|
||||||
|
|
||||||
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/download/{number}", name="set_download")
|
* @Route("/{number}/sets", name="rebrickable_set_sets")
|
||||||
*/
|
*/
|
||||||
public function downloadZipAction(Request $request, $number) {
|
public function setsAction(Set $set)
|
||||||
|
{
|
||||||
$em = $this->getDoctrine()->getManager();
|
$em = $this->getDoctrine()->getManager();
|
||||||
|
|
||||||
$inventoryParts = $em->getRepository(Inventory_Part::class)->findAllBySetNumber($number);
|
$inventorySets = $em->getRepository(Inventory_Set::class)->findAllBySetNumber($set->getNumber());
|
||||||
|
|
||||||
$zip = new \ZipArchive();
|
$template = $this->render('rebrickable/set/sets.html.twig', [
|
||||||
$zipName = 'set_'.$number.'.zip';
|
'inventorySets' => $inventorySets,
|
||||||
$zip->open($zipName, \ZipArchive::CREATE);
|
]);
|
||||||
/** @var Inventory_Part $part */
|
|
||||||
foreach ($inventoryParts as $part) {
|
|
||||||
$filename = $part->getPart()->getNumber().'_('.$part->getColor()->getName().'_'.$part->getQuantity().'x).stl';
|
|
||||||
|
|
||||||
try {
|
$json = json_encode($template->getContent());
|
||||||
if($part->getPart()->getModel()) {
|
$response = new Response($json, 200);
|
||||||
$zip->addFromString($filename, $this->get('oneup_flysystem.media_filesystem')->read($part->getPart()->getModel()->getPath()));
|
$response->headers->set('Content-Type', 'application/json');
|
||||||
}
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
dump($e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$zip->close();
|
|
||||||
|
|
||||||
$response = new Response(file_get_contents($zipName));
|
|
||||||
$response->headers->set('Content-Type', 'application/zip');
|
|
||||||
$response->headers->set('Content-Disposition', 'attachment;filename="' . $zipName . '"');
|
|
||||||
$response->headers->set('Content-length', filesize($zipName));
|
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
82
src/AppBundle/Controller/SetController.php
Normal file
82
src/AppBundle/Controller/SetController.php
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Controller;
|
||||||
|
|
||||||
|
use AppBundle\Api\Exception\ApiException;
|
||||||
|
use AppBundle\Api\Exception\EmptyResponseException;
|
||||||
|
use AppBundle\Entity\Rebrickable\Inventory_Part;
|
||||||
|
use AppBundle\Entity\Rebrickable\Set;
|
||||||
|
use AppBundle\Form\Filter\Set\SetFilterType;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/sets")
|
||||||
|
*/
|
||||||
|
class SetController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Route("/", name="set_index")
|
||||||
|
*/
|
||||||
|
public function indexAction(Request $request)
|
||||||
|
{
|
||||||
|
$form = $this->get('form.factory')->create(SetFilterType::class);
|
||||||
|
|
||||||
|
$filterBuilder = $this->get('repository.rebrickable.set')
|
||||||
|
->createQueryBuilder('s');
|
||||||
|
|
||||||
|
if ($request->query->has($form->getName())) {
|
||||||
|
// manually bind values from the request
|
||||||
|
$form->submit($request->query->get($form->getName()));
|
||||||
|
|
||||||
|
// build the query from the given form object
|
||||||
|
$this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $filterBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
$paginator = $this->get('knp_paginator');
|
||||||
|
$sets = $paginator->paginate(
|
||||||
|
$filterBuilder->getQuery(),
|
||||||
|
$request->query->getInt('page', 1)/*page number*/,
|
||||||
|
$request->query->getInt('limit', 30)/*limit per page*/
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->render('set/index.html.twig', [
|
||||||
|
'sets' => $sets,
|
||||||
|
'form' => $form->createView(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/{number}", name="set_detail")
|
||||||
|
*/
|
||||||
|
public function detailAction(Request $request, $number)
|
||||||
|
{
|
||||||
|
$rebrickableSet = null;
|
||||||
|
$bricksetSet = null;
|
||||||
|
try {
|
||||||
|
if (($rebrickableSet = $this->getDoctrine()->getManager()->getRepository(Set::class)->find($number)) == null) {
|
||||||
|
$this->addFlash('warning', 'Set not found in Rebrickable database');
|
||||||
|
}
|
||||||
|
|
||||||
|
$bricksetSet = $this->get('api.manager.brickset')->getSetByNumber($number);
|
||||||
|
dump($bricksetSet);
|
||||||
|
} catch (EmptyResponseException $e) {
|
||||||
|
$this->addFlash('warning', 'Set not found in Brickset database');
|
||||||
|
} catch (ApiException $e) {
|
||||||
|
$this->addFlash('error', $e->getService());
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->addFlash('error', $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$rebrickableSet && !$bricksetSet) {
|
||||||
|
return $this->render('error/error.html.twig');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->render('set/detail.html.twig', [
|
||||||
|
'rbset' => $rebrickableSet,
|
||||||
|
'brset' => $bricksetSet,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,7 @@ class Alias
|
|||||||
/**
|
/**
|
||||||
* @var Model
|
* @var Model
|
||||||
*
|
*
|
||||||
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\LDraw\Model", inversedBy="aliases", cascade={"persist"})
|
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\LDraw\Model", inversedBy="aliases")
|
||||||
*/
|
*/
|
||||||
private $model;
|
private $model;
|
||||||
|
|
||||||
|
34
src/AppBundle/Entity/LDraw/Author.php
Normal file
34
src/AppBundle/Entity/LDraw/Author.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Entity\LDraw;
|
||||||
|
|
||||||
|
use AppBundle\Entity\Traits\IdentityTrait;
|
||||||
|
use AppBundle\Entity\Traits\UniqueNameTrait;
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Author.
|
||||||
|
*
|
||||||
|
* @ORM\Table(name="ldraw_author")
|
||||||
|
* @ORM\Entity(repositoryClass="AppBundle\Repository\LDraw\AuthorRepository")
|
||||||
|
*/
|
||||||
|
class Author
|
||||||
|
{
|
||||||
|
use IdentityTrait;
|
||||||
|
use UniqueNameTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Author
|
||||||
|
*
|
||||||
|
* @ORM\OneToMany(targetEntity="AppBundle\Entity\LDraw\Model", mappedBy="author")
|
||||||
|
*/
|
||||||
|
private $models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Author
|
||||||
|
*/
|
||||||
|
public function getModels()
|
||||||
|
{
|
||||||
|
return $this->models;
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
namespace AppBundle\Entity\LDraw;
|
namespace AppBundle\Entity\LDraw;
|
||||||
|
|
||||||
use AppBundle\Entity\Traits\IdentityTrait;
|
use AppBundle\Entity\Traits\IdentityTrait;
|
||||||
use AppBundle\Entity\Traits\NameTrait;
|
use AppBundle\Entity\Traits\UniqueNameTrait;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
@ -17,7 +17,7 @@ use Doctrine\ORM\Mapping as ORM;
|
|||||||
class Category
|
class Category
|
||||||
{
|
{
|
||||||
use IdentityTrait;
|
use IdentityTrait;
|
||||||
use NameTrait;
|
use UniqueNameTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Collection
|
* @var Collection
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
namespace AppBundle\Entity\LDraw;
|
namespace AppBundle\Entity\LDraw;
|
||||||
|
|
||||||
use AppBundle\Entity\Traits\IdentityTrait;
|
use AppBundle\Entity\Traits\IdentityTrait;
|
||||||
use AppBundle\Entity\Traits\NameTrait;
|
use AppBundle\Entity\Traits\UniqueNameTrait;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ use Doctrine\ORM\Mapping as ORM;
|
|||||||
class Keyword
|
class Keyword
|
||||||
{
|
{
|
||||||
use IdentityTrait;
|
use IdentityTrait;
|
||||||
use NameTrait;
|
use UniqueNameTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ArrayCollection
|
* @var ArrayCollection
|
||||||
|
@ -17,13 +17,6 @@ class Model
|
|||||||
{
|
{
|
||||||
use NumberTrait;
|
use NumberTrait;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Type
|
|
||||||
*
|
|
||||||
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\LDraw\Type", inversedBy="models", cascade={"persist"})
|
|
||||||
*/
|
|
||||||
private $type;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*
|
*
|
||||||
@ -48,7 +41,7 @@ class Model
|
|||||||
/**
|
/**
|
||||||
* @var ArrayCollection
|
* @var ArrayCollection
|
||||||
*
|
*
|
||||||
* @ORM\OneToMany(targetEntity="AppBundle\Entity\LDraw\Subpart", mappedBy="parent")
|
* @ORM\OneToMany(targetEntity="AppBundle\Entity\LDraw\Subpart", mappedBy="parent", cascade={"persist"})
|
||||||
*/
|
*/
|
||||||
private $subparts;
|
private $subparts;
|
||||||
|
|
||||||
@ -74,9 +67,9 @@ class Model
|
|||||||
private $path;
|
private $path;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var Author
|
||||||
*
|
*
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\LDraw\Author", cascade={"persist"}, inversedBy="models")
|
||||||
*/
|
*/
|
||||||
private $author;
|
private $author;
|
||||||
|
|
||||||
@ -122,7 +115,7 @@ class Model
|
|||||||
/**
|
/**
|
||||||
* Set author.
|
* Set author.
|
||||||
*
|
*
|
||||||
* @param string $author
|
* @param Author $author
|
||||||
*
|
*
|
||||||
* @return Model
|
* @return Model
|
||||||
*/
|
*/
|
||||||
@ -136,7 +129,7 @@ class Model
|
|||||||
/**
|
/**
|
||||||
* Get author.
|
* Get author.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return Author
|
||||||
*/
|
*/
|
||||||
public function getAuthor()
|
public function getAuthor()
|
||||||
{
|
{
|
||||||
@ -163,22 +156,6 @@ class Model
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getType()
|
|
||||||
{
|
|
||||||
return $this->type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $type
|
|
||||||
*/
|
|
||||||
public function setType($type)
|
|
||||||
{
|
|
||||||
$this->type = $type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@ -292,6 +269,20 @@ class Model
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Subpart $subpart
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function addSubpart($subpart)
|
||||||
|
{
|
||||||
|
if (!$this->subparts->contains($subpart)) {
|
||||||
|
$this->subparts->add($subpart);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ArrayCollection
|
* @return ArrayCollection
|
||||||
*/
|
*/
|
||||||
|
@ -16,7 +16,7 @@ class Subpart
|
|||||||
* @var Model
|
* @var Model
|
||||||
*
|
*
|
||||||
* @ORM\Id
|
* @ORM\Id
|
||||||
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\LDraw\Model", inversedBy="subparts", cascade={"persist"})
|
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\LDraw\Model", inversedBy="subparts")
|
||||||
*/
|
*/
|
||||||
private $parent;
|
private $parent;
|
||||||
|
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace AppBundle\Entity\LDraw;
|
|
||||||
|
|
||||||
use AppBundle\Entity\Traits\IdentityTrait;
|
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
|
||||||
use Doctrine\Common\Collections\Collection;
|
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type.
|
|
||||||
*
|
|
||||||
* @ORM\Table(name="ldraw_type")
|
|
||||||
* @ORM\Entity(repositoryClass="AppBundle\Repository\LDraw\TypeRepository")
|
|
||||||
*/
|
|
||||||
class Type
|
|
||||||
{
|
|
||||||
use IdentityTrait;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*
|
|
||||||
* @ORM\Column(type="string", length=60, unique=true)
|
|
||||||
*/
|
|
||||||
private $name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Collection
|
|
||||||
*
|
|
||||||
* @ORM\OneToMany(targetEntity="Model", mappedBy="type")
|
|
||||||
*/
|
|
||||||
private $models;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BuildingKit constructor.
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->models = new ArrayCollection();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getName()
|
|
||||||
{
|
|
||||||
return $this->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $name
|
|
||||||
*/
|
|
||||||
public function setName($name)
|
|
||||||
{
|
|
||||||
$this->name = $name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get models.
|
|
||||||
*
|
|
||||||
* @return ArrayCollection
|
|
||||||
*/
|
|
||||||
public function getModels()
|
|
||||||
{
|
|
||||||
return $this->models;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Model $model
|
|
||||||
*
|
|
||||||
* @return Type
|
|
||||||
*/
|
|
||||||
public function addModel(Model $model)
|
|
||||||
{
|
|
||||||
$this->models->add($model);
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Model $model
|
|
||||||
*
|
|
||||||
* @return Type
|
|
||||||
*/
|
|
||||||
public function removeModel(Model $model)
|
|
||||||
{
|
|
||||||
$this->models->remove($model);
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
}
|
|
@ -38,9 +38,17 @@ class Inventory
|
|||||||
*/
|
*/
|
||||||
protected $inventoryParts;
|
protected $inventoryParts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Collection
|
||||||
|
*
|
||||||
|
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Rebrickable\Inventory_Set", mappedBy="inventory")
|
||||||
|
*/
|
||||||
|
protected $inventorySets;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->inventoryParts = new ArrayCollection();
|
$this->inventoryParts = new ArrayCollection();
|
||||||
|
$this->inventorySets = new ArrayCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,4 +98,20 @@ class Inventory
|
|||||||
{
|
{
|
||||||
$this->inventoryParts = $inventoryParts;
|
$this->inventoryParts = $inventoryParts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getInventorySets()
|
||||||
|
{
|
||||||
|
return $this->inventorySets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $inventorySets
|
||||||
|
*/
|
||||||
|
public function setInventorySets($inventorySets)
|
||||||
|
{
|
||||||
|
$this->inventorySets = $inventorySets;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ class Inventory_Part
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool
|
* @var bool
|
||||||
*
|
* @ORM\Id
|
||||||
* @ORM\Column(type="boolean")
|
* @ORM\Column(type="boolean")
|
||||||
*/
|
*/
|
||||||
protected $spare;
|
protected $spare;
|
||||||
|
81
src/AppBundle/Entity/Rebrickable/Inventory_Set.php
Normal file
81
src/AppBundle/Entity/Rebrickable/Inventory_Set.php
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Entity\Rebrickable;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inventory_Set.
|
||||||
|
*
|
||||||
|
* @ORM\Table(name="rebrickable_inventory_sets")
|
||||||
|
* @ORM\Entity(repositoryClass="AppBundle\Repository\Rebrickable\Inventory_SetRepository")
|
||||||
|
*/
|
||||||
|
class Inventory_Set
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Inventory
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Rebrickable\Inventory", inversedBy="inventorySets")
|
||||||
|
*/
|
||||||
|
protected $inventory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Set
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Rebrickable\Set", inversedBy="inventorySets")
|
||||||
|
*/
|
||||||
|
protected $set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*
|
||||||
|
* @ORM\Column(type="integer")
|
||||||
|
*/
|
||||||
|
protected $quantity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get count.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getQuantity()
|
||||||
|
{
|
||||||
|
return $this->quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Set
|
||||||
|
*/
|
||||||
|
public function getSet()
|
||||||
|
{
|
||||||
|
return $this->set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Set $set
|
||||||
|
*/
|
||||||
|
public function setSet($set)
|
||||||
|
{
|
||||||
|
$this->set = $set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Inventory
|
||||||
|
*/
|
||||||
|
public function getInventory()
|
||||||
|
{
|
||||||
|
return $this->inventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Inventory $inventory
|
||||||
|
*
|
||||||
|
* @return Inventory_Set
|
||||||
|
*/
|
||||||
|
public function setInventory(Inventory $inventory)
|
||||||
|
{
|
||||||
|
$this->inventory = $inventory;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
@ -47,12 +47,20 @@ class Set
|
|||||||
*/
|
*/
|
||||||
protected $theme;
|
protected $theme;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Collection
|
||||||
|
*
|
||||||
|
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Rebrickable\Inventory_Set", mappedBy="set")
|
||||||
|
*/
|
||||||
|
protected $inventorySets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set constructor.
|
* Set constructor.
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->inventories = new ArrayCollection();
|
$this->inventories = new ArrayCollection();
|
||||||
|
$this->inventorySets = new ArrayCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,6 +141,22 @@ class Set
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getInventorySets()
|
||||||
|
{
|
||||||
|
return $this->inventorySets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $inventorySets
|
||||||
|
*/
|
||||||
|
public function setInventorySets($inventorySets)
|
||||||
|
{
|
||||||
|
$this->inventorySets = $inventorySets;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Theme
|
* @return Theme
|
||||||
*/
|
*/
|
||||||
|
33
src/AppBundle/Entity/Traits/UniqueNameTrait.php
Normal file
33
src/AppBundle/Entity/Traits/UniqueNameTrait.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Entity\Traits;
|
||||||
|
|
||||||
|
trait UniqueNameTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*
|
||||||
|
* @ORM\Column(type="string", length=255, nullable=true, unique=true)
|
||||||
|
*/
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function setName($name)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
35
src/AppBundle/Exception/ConvertingFailedException.php
Normal file
35
src/AppBundle/Exception/ConvertingFailedException.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Exception;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class ConvertingFailedException extends \Exception
|
||||||
|
{
|
||||||
|
private $filepath;
|
||||||
|
|
||||||
|
public function __construct($form = '', $to = '', $message = '', $code = 0, Exception $previous = null)
|
||||||
|
{
|
||||||
|
$message = sprintf('Error converting "%s" file to "%s".', $form, $to);
|
||||||
|
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
|
||||||
|
$this->filepath = $form;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getFilepath()
|
||||||
|
{
|
||||||
|
return $this->filepath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $filepath
|
||||||
|
*/
|
||||||
|
public function setFilepath($filepath)
|
||||||
|
{
|
||||||
|
$this->filepath = $filepath;
|
||||||
|
}
|
||||||
|
}
|
15
src/AppBundle/Exception/ErrorParsingLineException.php
Normal file
15
src/AppBundle/Exception/ErrorParsingLineException.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Exception;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class ErrorParsingLineException extends FileException
|
||||||
|
{
|
||||||
|
public function __construct($path, $line, $message = '', $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = sprintf('Error parsing line \""%s"\" "%s" file.',$line, $path);
|
||||||
|
|
||||||
|
parent::__construct($path, $message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
17
src/AppBundle/Exception/FileException.php
Normal file
17
src/AppBundle/Exception/FileException.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Exception;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class FileException extends \Exception
|
||||||
|
{
|
||||||
|
protected $path;
|
||||||
|
|
||||||
|
public function __construct($path, $message = '', $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$this->path = $path;
|
||||||
|
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
15
src/AppBundle/Exception/FileNotFoundException.php
Normal file
15
src/AppBundle/Exception/FileNotFoundException.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Exception;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class FileNotFoundException extends FileException
|
||||||
|
{
|
||||||
|
public function __construct($path, $message = '', $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = sprintf('File "%s" not found.', $path);
|
||||||
|
|
||||||
|
parent::__construct($path, $message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
15
src/AppBundle/Exception/ParseErrorException.php
Normal file
15
src/AppBundle/Exception/ParseErrorException.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Exception;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class ParseErrorException extends FileException
|
||||||
|
{
|
||||||
|
public function __construct($path, $message = '', $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = sprintf('Error parsing "%s" file.', $path);
|
||||||
|
|
||||||
|
parent::__construct($path, $message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
15
src/AppBundle/Exception/WriteErrorException.php
Normal file
15
src/AppBundle/Exception/WriteErrorException.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Exception;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class WriteErrorException extends FileException
|
||||||
|
{
|
||||||
|
public function __construct($file, $message = '', $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$message = sprintf('Could not write into "%s" file.', $file);
|
||||||
|
|
||||||
|
parent::__construct($file, $message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace AppBundle\Form\Filter;
|
namespace AppBundle\Form\Filter\Model;
|
||||||
|
|
||||||
use AppBundle\Entity\LDraw\Category;
|
use AppBundle\Entity\LDraw\Category;
|
||||||
use AppBundle\Manager\LDraw\CategoryManager;
|
use AppBundle\Repository\LDraw\CategoryRepository;
|
||||||
use Lexik\Bundle\FormFilterBundle\Filter\Form\Type as Filters;
|
use Lexik\Bundle\FormFilterBundle\Filter\Form\Type as Filters;
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
@ -11,17 +11,17 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
|||||||
|
|
||||||
class CategoryFilterType extends AbstractType
|
class CategoryFilterType extends AbstractType
|
||||||
{
|
{
|
||||||
private $categoryManager;
|
private $categoryRepository;
|
||||||
|
|
||||||
public function __construct(CategoryManager $categoryManager)
|
public function __construct(CategoryRepository $categoryRepository)
|
||||||
{
|
{
|
||||||
$this->categoryManager = $categoryManager;
|
$this->categoryRepository = $categoryRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
{
|
{
|
||||||
$builder->add('id', Filters\ChoiceFilterType::class, [
|
$builder->add('id', Filters\ChoiceFilterType::class, [
|
||||||
'choices' => $this->categoryManager->findAll(),
|
'choices' => $this->categoryRepository->findAll(),
|
||||||
'choice_label' => 'name',
|
'choice_label' => 'name',
|
||||||
'label' => 'filter.part.category',
|
'label' => 'filter.part.category',
|
||||||
]);
|
]);
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace AppBundle\Form\Filter;
|
namespace AppBundle\Form\Filter\Model;
|
||||||
|
|
||||||
use Doctrine\ORM\QueryBuilder;
|
use Doctrine\ORM\QueryBuilder;
|
||||||
use Lexik\Bundle\FormFilterBundle\Filter\FilterBuilderExecuterInterface;
|
use Lexik\Bundle\FormFilterBundle\Filter\FilterBuilderExecuterInterface;
|
58
src/AppBundle/Form/Filter/Set/SetFilterType.php
Normal file
58
src/AppBundle/Form/Filter/Set/SetFilterType.php
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Form\Filter\Set;
|
||||||
|
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Lexik\Bundle\FormFilterBundle\Filter\FilterBuilderExecuterInterface;
|
||||||
|
use Lexik\Bundle\FormFilterBundle\Filter\Form\Type as Filters;
|
||||||
|
use Lexik\Bundle\FormFilterBundle\Filter\Query\QueryInterface;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
class SetFilterType extends AbstractType
|
||||||
|
{
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
|
{
|
||||||
|
$builder->add('search', Filters\TextFilterType::class, [
|
||||||
|
'apply_filter' => [$this, 'setSearchCallback'],
|
||||||
|
'label' => 'filter.part.search',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$builder->add('theme', ThemeFilterType::class, [
|
||||||
|
'add_shared' => function (FilterBuilderExecuterInterface $builderExecuter) {
|
||||||
|
$builderExecuter->addOnce($builderExecuter->getAlias().'.theme', 'c', function (QueryBuilder $filterBuilder, $alias, $joinAlias, $expr) {
|
||||||
|
$filterBuilder->leftJoin($alias.'.theme', $joinAlias);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBlockPrefix()
|
||||||
|
{
|
||||||
|
return 'model_filter';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'csrf_protection' => false,
|
||||||
|
'validation_groups' => ['filtering'], // avoid NotBlank() constraint-related message
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSearchCallback(QueryInterface $filterQuery, $field, $values)
|
||||||
|
{
|
||||||
|
if (empty($values['value'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// expression that represent the condition
|
||||||
|
$expression = $filterQuery->getExpr()->orX(
|
||||||
|
$filterQuery->getExpr()->like('s.name', ':value'),
|
||||||
|
$filterQuery->getExpr()->like('s.number', ':value')
|
||||||
|
);
|
||||||
|
|
||||||
|
return $filterQuery->createCondition($expression, ['value' => '%'.$values['value'].'%']);
|
||||||
|
}
|
||||||
|
}
|
63
src/AppBundle/Form/Filter/Set/ThemeFilterType.php
Normal file
63
src/AppBundle/Form/Filter/Set/ThemeFilterType.php
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Form\Filter\Set;
|
||||||
|
|
||||||
|
use AppBundle\Entity\Rebrickable\Theme;
|
||||||
|
use AppBundle\Repository\Rebrickable\ThemeRepository;
|
||||||
|
use Lexik\Bundle\FormFilterBundle\Filter\Form\Type as Filters;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
class ThemeFilterType extends AbstractType
|
||||||
|
{
|
||||||
|
private $themeRepository;
|
||||||
|
|
||||||
|
public function __construct(ThemeRepository $themeRepository)
|
||||||
|
{
|
||||||
|
$this->themeRepository = $themeRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
|
{
|
||||||
|
$builder->add('id', Filters\ChoiceFilterType::class, [
|
||||||
|
'choices' => $this->themeRepository->findAll(),
|
||||||
|
'choice_label' => function ($theme, $currentChoiceKey) {
|
||||||
|
if ($parent = $theme->getParent()) {
|
||||||
|
if ($parentParent = $parent->getParent()) {
|
||||||
|
if ($parentParentParent = $parentParent->getParent()) {
|
||||||
|
return $parentParentParent->getName().' > '.$parentParent->getName().' > '.$parent->getName().' > '.$theme->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $parentParent->getName().' > '.$parent->getName().' > '.$theme->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $parent->getName().' > '.$theme->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $theme->getName();
|
||||||
|
},
|
||||||
|
'label' => 'filter.set.theme',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParent()
|
||||||
|
{
|
||||||
|
return Filters\SharedableFilterType::class; // this allow us to use the "add_shared" option
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBlockPrefix()
|
||||||
|
{
|
||||||
|
return 'theme_filter';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDefaultOptions(OptionsResolver $resolver)
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'data_class' => Theme::class,
|
||||||
|
'csrf_protection' => false,
|
||||||
|
'validation_groups' => ['filtering'], // avoid NotBlank() constraint-related message
|
||||||
|
'method' => 'GET',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace AppBundle\Manager;
|
|
||||||
|
|
||||||
class BaseManager
|
|
||||||
{
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function getRepository()
|
|
||||||
{
|
|
||||||
return $this->repository;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace AppBundle\Manager\LDraw;
|
|
||||||
|
|
||||||
use AppBundle\Entity\LDraw\Alias;
|
|
||||||
use AppBundle\Entity\LDraw\Model;
|
|
||||||
use AppBundle\Manager\BaseManager;
|
|
||||||
use AppBundle\Repository\LDraw\AliasRepository;
|
|
||||||
|
|
||||||
class AliasManager extends BaseManager
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* AliasManager constructor.
|
|
||||||
*
|
|
||||||
* @param AliasRepository $repository
|
|
||||||
*/
|
|
||||||
public function __construct(AliasRepository $repository)
|
|
||||||
{
|
|
||||||
$this->repository = $repository;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new Alias entity.
|
|
||||||
*
|
|
||||||
* @param $number
|
|
||||||
* @param Model $model
|
|
||||||
*
|
|
||||||
* @return Alias
|
|
||||||
*/
|
|
||||||
public function create($number, $model)
|
|
||||||
{
|
|
||||||
if (($alias = $this->repository->findOneBy(['number' => $number, 'model' => $model])) == null) {
|
|
||||||
$alias = new Alias();
|
|
||||||
$alias->setModel($model);
|
|
||||||
$alias->setNumber($number);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $alias;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace AppBundle\Manager\LDraw;
|
|
||||||
|
|
||||||
use AppBundle\Entity\LDraw\Category;
|
|
||||||
use AppBundle\Manager\BaseManager;
|
|
||||||
use AppBundle\Repository\LDraw\CategoryRepository;
|
|
||||||
|
|
||||||
class CategoryManager extends BaseManager
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* CategoryManager constructor.
|
|
||||||
*
|
|
||||||
* @param CategoryRepository $repository
|
|
||||||
*/
|
|
||||||
public function __construct(CategoryRepository $repository)
|
|
||||||
{
|
|
||||||
$this->repository = $repository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function findAll()
|
|
||||||
{
|
|
||||||
return $this->repository->findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new Category entity with $name or retrieve one.
|
|
||||||
*
|
|
||||||
* @param $name
|
|
||||||
*
|
|
||||||
* @return Category
|
|
||||||
*/
|
|
||||||
public function create($name)
|
|
||||||
{
|
|
||||||
if (($category = $this->repository->findByName($name)) == null) {
|
|
||||||
$category = new Category();
|
|
||||||
$category->setName($name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $category;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace AppBundle\Manager\LDraw;
|
|
||||||
|
|
||||||
use AppBundle\Entity\LDraw\Keyword;
|
|
||||||
use AppBundle\Manager\BaseManager;
|
|
||||||
use AppBundle\Repository\LDraw\KeywordRepository;
|
|
||||||
|
|
||||||
class KeywordManager extends BaseManager
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* KeywordManager constructor.
|
|
||||||
*
|
|
||||||
* @param KeywordRepository $repository
|
|
||||||
*/
|
|
||||||
public function __construct(KeywordRepository $repository)
|
|
||||||
{
|
|
||||||
$this->repository = $repository;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new Keyword entity with $name or retrieve one.
|
|
||||||
*
|
|
||||||
* @param $name
|
|
||||||
*
|
|
||||||
* @return Keyword
|
|
||||||
*/
|
|
||||||
public function create($name)
|
|
||||||
{
|
|
||||||
if (($keyword = $this->repository->findByName($name)) == null) {
|
|
||||||
$keyword = new Keyword();
|
|
||||||
$keyword->setName($name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $keyword;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace AppBundle\Manager\LDraw;
|
|
||||||
|
|
||||||
use AppBundle\Entity\LDraw\Model;
|
|
||||||
use AppBundle\Manager\BaseManager;
|
|
||||||
use AppBundle\Repository\LDraw\ModelRepository;
|
|
||||||
|
|
||||||
class ModelManager extends BaseManager
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* ModelManager constructor.
|
|
||||||
*
|
|
||||||
* @param ModelRepository $repository
|
|
||||||
*/
|
|
||||||
public function __construct(ModelRepository $repository)
|
|
||||||
{
|
|
||||||
$this->repository = $repository;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new Model entity with $number or retrieve one.
|
|
||||||
*
|
|
||||||
* @param $number
|
|
||||||
*
|
|
||||||
* @return Model
|
|
||||||
*/
|
|
||||||
public function create($number)
|
|
||||||
{
|
|
||||||
if (($model = $this->repository->findOneBy(['number' => $number])) == null) {
|
|
||||||
$model = new Model();
|
|
||||||
$model->setNumber($number);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function findByNumber($number)
|
|
||||||
{
|
|
||||||
return $this->repository->findOneByNumber($number);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function findByName($name)
|
|
||||||
{
|
|
||||||
return $this->repository->findOneBy(['name' => $name]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace AppBundle\Manager\LDraw;
|
|
||||||
|
|
||||||
use AppBundle\Entity\LDraw\Subpart;
|
|
||||||
use AppBundle\Manager\BaseManager;
|
|
||||||
use AppBundle\Repository\LDraw\SubpartRepository;
|
|
||||||
|
|
||||||
class SubpartManager extends BaseManager
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* SubpartManager constructor.
|
|
||||||
*
|
|
||||||
* @param SubpartRepository $repository
|
|
||||||
*/
|
|
||||||
public function __construct(SubpartRepository $repository)
|
|
||||||
{
|
|
||||||
$this->repository = $repository;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new Subpart relation entity or retrieve one by foreign keys.
|
|
||||||
*
|
|
||||||
* @param $name
|
|
||||||
*
|
|
||||||
* @return Subpart
|
|
||||||
*/
|
|
||||||
public function create($parent, $child)
|
|
||||||
{
|
|
||||||
if (($subpart = $this->repository->findOneByKeys($parent, $child))) {
|
|
||||||
$subpart->setCount($subpart->getCount() + 1);
|
|
||||||
} else {
|
|
||||||
$subpart = new Subpart();
|
|
||||||
$subpart
|
|
||||||
->setParent($parent)
|
|
||||||
->setSubpart($child)
|
|
||||||
->setCount(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $subpart;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace AppBundle\Manager\LDraw;
|
|
||||||
|
|
||||||
use AppBundle\Entity\LDraw\Type;
|
|
||||||
use AppBundle\Manager\BaseManager;
|
|
||||||
use AppBundle\Repository\LDraw\TypeRepository;
|
|
||||||
|
|
||||||
class TypeManager extends BaseManager
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* TypeManager constructor.
|
|
||||||
*
|
|
||||||
* @param TypeRepository $typeRepository
|
|
||||||
*/
|
|
||||||
public function __construct(TypeRepository $repository)
|
|
||||||
{
|
|
||||||
$this->repository = $repository;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new Keyword entity with $name or retrieve one.
|
|
||||||
*
|
|
||||||
* @param $name
|
|
||||||
*
|
|
||||||
* @return Type
|
|
||||||
*/
|
|
||||||
public function create($name)
|
|
||||||
{
|
|
||||||
if (($type = $this->repository->findByName($name)) == null) {
|
|
||||||
$type = new Type();
|
|
||||||
$type->setName($name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $type;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,99 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace AppBundle\Manager;
|
|
||||||
|
|
||||||
use AppBundle\Manager\LDraw\AliasManager;
|
|
||||||
use AppBundle\Manager\LDraw\CategoryManager;
|
|
||||||
use AppBundle\Manager\LDraw\KeywordManager;
|
|
||||||
use AppBundle\Manager\LDraw\ModelManager;
|
|
||||||
use AppBundle\Manager\LDraw\SubpartManager;
|
|
||||||
use AppBundle\Manager\LDraw\TypeManager;
|
|
||||||
|
|
||||||
class LDrawManager
|
|
||||||
{
|
|
||||||
/** @var CategoryManager */
|
|
||||||
private $categoryManager;
|
|
||||||
|
|
||||||
/** @var KeywordManager */
|
|
||||||
private $keywordManager;
|
|
||||||
|
|
||||||
/** @var TypeManager */
|
|
||||||
private $typeManager;
|
|
||||||
|
|
||||||
/** @var SubpartManager */
|
|
||||||
private $subpartManager;
|
|
||||||
|
|
||||||
/** @var ModelManager */
|
|
||||||
private $modelManager;
|
|
||||||
|
|
||||||
/** @var AliasManager */
|
|
||||||
private $aliasManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* LDrawService constructor.
|
|
||||||
*
|
|
||||||
* @param CategoryManager $categoryManager
|
|
||||||
* @param KeywordManager $keywordManager
|
|
||||||
* @param TypeManager $typeManager
|
|
||||||
* @param SubpartManager $subpartManager
|
|
||||||
* @param ModelManager $modelManager
|
|
||||||
* @param AliasManager $aliasManager
|
|
||||||
*/
|
|
||||||
public function __construct(CategoryManager $categoryManager, KeywordManager $keywordManager, TypeManager $typeManager, SubpartManager $subpartManager, ModelManager $modelManager, AliasManager $aliasManager)
|
|
||||||
{
|
|
||||||
$this->categoryManager = $categoryManager;
|
|
||||||
$this->keywordManager = $keywordManager;
|
|
||||||
$this->typeManager = $typeManager;
|
|
||||||
$this->subpartManager = $subpartManager;
|
|
||||||
$this->modelManager = $modelManager;
|
|
||||||
$this->aliasManager = $aliasManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function getCategoryManager()
|
|
||||||
{
|
|
||||||
return $this->categoryManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function getKeywordManager()
|
|
||||||
{
|
|
||||||
return $this->keywordManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return TypeManager
|
|
||||||
*/
|
|
||||||
public function getTypeManager()
|
|
||||||
{
|
|
||||||
return $this->typeManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return SubpartManager
|
|
||||||
*/
|
|
||||||
public function getSubpartManager()
|
|
||||||
{
|
|
||||||
return $this->subpartManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return ModelManager
|
|
||||||
*/
|
|
||||||
public function getModelManager()
|
|
||||||
{
|
|
||||||
return $this->modelManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return AliasManager
|
|
||||||
*/
|
|
||||||
public function getAliasManager()
|
|
||||||
{
|
|
||||||
return $this->aliasManager;
|
|
||||||
}
|
|
||||||
}
|
|
@ -35,7 +35,7 @@ class Builder
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$menu->addChild('Models', [
|
$menu->addChild('Models', [
|
||||||
'route' => 'ldraw_model_index',
|
'route' => 'model_index',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$menu->addChild('Sets', [
|
$menu->addChild('Sets', [
|
||||||
|
@ -2,8 +2,28 @@
|
|||||||
|
|
||||||
namespace AppBundle\Repository\LDraw;
|
namespace AppBundle\Repository\LDraw;
|
||||||
|
|
||||||
|
use AppBundle\Entity\LDraw\Alias;
|
||||||
|
use AppBundle\Entity\LDraw\Model;
|
||||||
use AppBundle\Repository\BaseRepository;
|
use AppBundle\Repository\BaseRepository;
|
||||||
|
|
||||||
class AliasRepository extends BaseRepository
|
class AliasRepository extends BaseRepository
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Get existing entity or create new.
|
||||||
|
*
|
||||||
|
* @param $number
|
||||||
|
* @param Model $model
|
||||||
|
*
|
||||||
|
* @return Alias
|
||||||
|
*/
|
||||||
|
public function getOrCreate($number, $model)
|
||||||
|
{
|
||||||
|
if (($alias = $this->findOneBy(['number' => $number, 'model' => $model])) == null) {
|
||||||
|
$alias = new Alias();
|
||||||
|
$alias->setModel($model);
|
||||||
|
$alias->setNumber($number);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $alias;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
31
src/AppBundle/Repository/LDraw/AuthorRepository.php
Normal file
31
src/AppBundle/Repository/LDraw/AuthorRepository.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AppBundle\Repository\LDraw;
|
||||||
|
|
||||||
|
use AppBundle\Entity\LDraw\Author;
|
||||||
|
use AppBundle\Repository\BaseRepository;
|
||||||
|
|
||||||
|
class AuthorRepository extends BaseRepository
|
||||||
|
{
|
||||||
|
public function findOneByName($name)
|
||||||
|
{
|
||||||
|
return $this->findOneBy(['name' => $name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get existing entity or create new.
|
||||||
|
*
|
||||||
|
* @param $name
|
||||||
|
*
|
||||||
|
* @return Author
|
||||||
|
*/
|
||||||
|
public function getOrCreate($name)
|
||||||
|
{
|
||||||
|
if (($author = $this->findOneByName($name)) == null) {
|
||||||
|
$author = new Author();
|
||||||
|
$author->setName($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $author;
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace AppBundle\Repository\LDraw;
|
namespace AppBundle\Repository\LDraw;
|
||||||
|
|
||||||
|
use AppBundle\Entity\LDraw\Category;
|
||||||
use AppBundle\Repository\BaseRepository;
|
use AppBundle\Repository\BaseRepository;
|
||||||
|
|
||||||
class CategoryRepository extends BaseRepository
|
class CategoryRepository extends BaseRepository
|
||||||
@ -10,4 +11,21 @@ class CategoryRepository extends BaseRepository
|
|||||||
{
|
{
|
||||||
return $this->findOneBy(['name' => $name]);
|
return $this->findOneBy(['name' => $name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get existing entity or create new.
|
||||||
|
*
|
||||||
|
* @param $name
|
||||||
|
*
|
||||||
|
* @return Category
|
||||||
|
*/
|
||||||
|
public function getOrCreate($name)
|
||||||
|
{
|
||||||
|
if (($category = $this->findByName($name)) == null) {
|
||||||
|
$category = new Category();
|
||||||
|
$category->setName($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $category;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace AppBundle\Repository\LDraw;
|
namespace AppBundle\Repository\LDraw;
|
||||||
|
|
||||||
|
use AppBundle\Entity\LDraw\Keyword;
|
||||||
use AppBundle\Repository\BaseRepository;
|
use AppBundle\Repository\BaseRepository;
|
||||||
|
|
||||||
class KeywordRepository extends BaseRepository
|
class KeywordRepository extends BaseRepository
|
||||||
@ -10,4 +11,21 @@ class KeywordRepository extends BaseRepository
|
|||||||
{
|
{
|
||||||
return $this->findOneBy(['name' => $name]);
|
return $this->findOneBy(['name' => $name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new Keyword entity with $name or retrieve one.
|
||||||
|
*
|
||||||
|
* @param $name
|
||||||
|
*
|
||||||
|
* @return Keyword
|
||||||
|
*/
|
||||||
|
public function getOrCreate($name)
|
||||||
|
{
|
||||||
|
if (($keyword = $this->findByName($name)) == null) {
|
||||||
|
$keyword = new Keyword();
|
||||||
|
$keyword->setName($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $keyword;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,30 +2,33 @@
|
|||||||
|
|
||||||
namespace AppBundle\Repository\LDraw;
|
namespace AppBundle\Repository\LDraw;
|
||||||
|
|
||||||
use AppBundle\Entity\Rebrickable\Set;
|
|
||||||
use AppBundle\Entity\Rebrickable\Part;
|
|
||||||
use AppBundle\Entity\LDraw\Alias;
|
use AppBundle\Entity\LDraw\Alias;
|
||||||
use AppBundle\Entity\LDraw\Type;
|
use AppBundle\Entity\LDraw\Category;
|
||||||
|
use AppBundle\Entity\LDraw\Model;
|
||||||
|
use AppBundle\Entity\LDraw\Subpart;
|
||||||
use AppBundle\Entity\Rebrickable\Inventory;
|
use AppBundle\Entity\Rebrickable\Inventory;
|
||||||
use AppBundle\Entity\Rebrickable\Inventory_Part;
|
use AppBundle\Entity\Rebrickable\Inventory_Part;
|
||||||
|
use AppBundle\Entity\Rebrickable\Part;
|
||||||
|
use AppBundle\Entity\Rebrickable\Set;
|
||||||
use AppBundle\Repository\BaseRepository;
|
use AppBundle\Repository\BaseRepository;
|
||||||
use Doctrine\ORM\Query\Expr\Join;
|
use Doctrine\ORM\Query\Expr\Join;
|
||||||
|
|
||||||
class ModelRepository extends BaseRepository
|
class ModelRepository extends BaseRepository
|
||||||
{
|
{
|
||||||
public function findAllByType($type)
|
public function getFilteredQueryBuilder()
|
||||||
{
|
{
|
||||||
$queryBuilder = $this->createQueryBuilder('model')
|
$queryBuilder = $this->createQueryBuilder('model')
|
||||||
->join(Type::class, 'type', Join::LEFT_JOIN, 'model.type = :type')
|
// ->where('model.name NOT LIKE :obsolete')
|
||||||
->setParameter('type', $type);
|
// ->setParameter('obsolete','~%')
|
||||||
|
;
|
||||||
|
|
||||||
return $queryBuilder->getQuery();
|
return $queryBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findAllByCategory($category)
|
public function findAllByCategory($category)
|
||||||
{
|
{
|
||||||
$queryBuilder = $this->createQueryBuilder('model')
|
$queryBuilder = $this->createQueryBuilder('model')
|
||||||
->join(Type::class, 'type', Join::LEFT_JOIN, 'model.category = :category')
|
->join(Category::class, 'type', Join::LEFT_JOIN, 'model.category = :category')
|
||||||
->setParameter('category', $category);
|
->setParameter('category', $category);
|
||||||
|
|
||||||
return $queryBuilder->getQuery();
|
return $queryBuilder->getQuery();
|
||||||
@ -49,6 +52,11 @@ class ModelRepository extends BaseRepository
|
|||||||
return $model;
|
return $model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function findOneByName($name)
|
||||||
|
{
|
||||||
|
return $this->findOneBy(['name' => $name]);
|
||||||
|
}
|
||||||
|
|
||||||
public function findAllBySetNumber($number)
|
public function findAllBySetNumber($number)
|
||||||
{
|
{
|
||||||
$queryBuilder = $this->createQueryBuilder('model');
|
$queryBuilder = $this->createQueryBuilder('model');
|
||||||
@ -64,4 +72,38 @@ class ModelRepository extends BaseRepository
|
|||||||
|
|
||||||
return $queryBuilder->getQuery()->getResult();
|
return $queryBuilder->getQuery()->getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function findAllRelatedModels($number)
|
||||||
|
{
|
||||||
|
$queryBuilder = $this->createQueryBuilder('model');
|
||||||
|
|
||||||
|
$queryBuilder
|
||||||
|
->select('related')
|
||||||
|
->join(Subpart::class, 'subpart', JOIN::WITH, 'model.number = subpart.subpart')
|
||||||
|
->join(Subpart::class, 'parent', JOIN::WITH, 'subpart.parent = parent.parent')
|
||||||
|
->join(Model::class, 'related', JOIN::WITH, 'related.number = parent.subpart')
|
||||||
|
->where('model.number = :number')
|
||||||
|
->setParameter('number', $number)
|
||||||
|
->andWhere('related.number != :number')
|
||||||
|
->distinct(true);
|
||||||
|
|
||||||
|
return $queryBuilder->getQuery()->getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new Model entity with $number or retrieve one.
|
||||||
|
*
|
||||||
|
* @param $number
|
||||||
|
*
|
||||||
|
* @return Model
|
||||||
|
*/
|
||||||
|
public function getOrCreate($number)
|
||||||
|
{
|
||||||
|
if (($model = $this->findOneBy(['number' => $number])) == null) {
|
||||||
|
$model = new Model();
|
||||||
|
$model->setNumber($number);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $model;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user