Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First commit #4

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM composer
RUN composer global require "laravel/lumen-installer"
ENV PATH $PATH:/tmp/vendor/bin
Binary file added Lumen_browser.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Lumen_splash.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
111 changes: 10 additions & 101 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,112 +1,21 @@
# Back-end Coding Exercise
# ShootProof Psuedo Api

Per the ShootProof test, this is a mock api. It is built in Lumen MVC.

## Overview
### Docker

Here at ShootProof, we prefer to have a good idea of a candidate's technical
experience before proceeding with portions of our recruiting process. We
believe that the technical exercise below will illustrate a candidate's
approach to working with technologies commonly used here at ShootProof.
The app was used built using docker, which means it should run on any environment. To use docker, please do `docker-compose up`.

### Database

## Guidelines
All the database related information (tables, indexes, foriegns, etc) can be found in `images/php/app/database/migrations`

The exercise consists of several different parts designed to showcase your
problem-solving and solution-implementation talents. There is not a single
correct answer; this is *not* an exam. We simply want to see how you approach a
business problem and the steps you take to solve it.
### Model

* This exercise should not take you more than two or three hours to complete. If
your solution is taking longer, that's okay—be honest and let us know how long
it took and why you think it took that long.
* Be as thorough as you wish.
* All exercises are to be performed as if you were on the job.
* You may submit your response in one of the following ways:
* Package an archive (ZIP, tarball, etc.) of your files and deliver it to
your contact.
* If working with a recruiter, deliver it to them.
* If working with ShootProof directly, deliver to <[email protected]>.
* Fork our repository and open a pull request.
The models are the logic used to interface witht he database. They are found in `images/php/app/app/`. They are Album, Gallery, Photo, and the other model files.

### Restful API

## Exercise
The restful routes for the API can be found in `images/php/app/routes/web.php`. The routes are caught by controllers in `images/php/app/app/http/Controllers/`.

Imagine that it's 2010, and ShootProof are starting to build our photo uploading
and processing functionality. This exercise walks you through what it might take
to design and build a very small portion of the ShootProof photo galleries
feature.


### Part 1: Data/domain modeling

**Goal:** define a data/domain model for photo galleries that contains albums
and photos.

Define a data model that:

* Allows a user to create a photo gallery.
* Allows the photo gallery to have photos uploaded into it.
* Allows the photo gallery to contain zero or more albums.
* Optionally allows a photo to be placed within one or more albums.

A complete submission will:

* Define all the relevant entities in the model.
* Illustrate the relationships and, optionally, behaviors among the entities.
* Describe the properties of each entity.
* Be documented in a manner you deem appropriate to accomplish the goal
(entity-relationship diagram, UML, etc.).

#### Extra credit

* Include data definition language (DDL) statements to create tables for the
data model. Define the columns present in each table, along with their data
type and size.


### Part 2: Object-oriented programming

**Goal:** convert the data/domain model defined in Part 1 into working PHP
classes.

A complete submission will:

* Define all the relevant namespaces and classes as illustrated in your model.
* Include functionality to access and manipulate the data properties of each
entity in the model.
* Expose the relationships among the entities through the use of code.

*Please note: Making database requests from these classes is not in the scope
of this exercise. Instead, focus on translating the domain into classes.*

#### Extra credit

* Include code to illustrate any behaviors you've considered (this may be
stubbed code).
* Include unit tests for these classes; if included, we should be able to run
the tests to see them passing.
* Show the use of a third-party dependency integrated and used within your
classes.


### (Optional) Part 3: Hypermedia API design (REST)

**Goal:** design endpoints for a hypermedia API that will be used by API
consumers to create, read, update, and delete galleries, albums, and photos.

A complete submission will:

* Design JSON data structures for use in API requests and responses.
* Illustrate what each of your data/domain model entities would look like when
returned from the API.
* Expose relationships among the entities through the use of hypermedia.
* Define all the operations that may be performed on each entity through the API
and map HTTP methods to these operations.
* Show example HTTP requests and responses.

#### Extra credit

* Document the API in a manner you deem appropriate to accomplish the goal
(OpenAPI, API Blueprint, Markdown, etc.).
* Describe the HTTP status codes that might be returned by each operation.
* Design API error responses that might occur for certain operations.
42 changes: 42 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
nginx:
build: images/nginx
command: nginx -g "daemon off;"
links:
- php
ports:
- "80:80"
php:
build: images/php
volumes:
- ./images/php:/var/www/html
working_dir: /var/www/html/app/public
command: php-fpm
links:
- db
- cache
ports:
- "9000:9000"
environment:
APP_ENV: local
APP_DEBUG: 'true'
APP_KEY: SomeRandomKey!!!
APP_LOCALE: en
APP_FALLBACK_LOCALE: en
DB_CONNECTION: mysql
DB_HOST: db
DB_DATABASE: lumen
DB_USERNAME: lumen
DB_PASSWORD: secret
MEMCACHED_HOST: cache
CACHE_DRIVER: memcached
db:
image: mysql
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: lumen
MYSQL_USER: lumen
MYSQL_PASSWORD: secret
cache:
image: memcached
2 changes: 2 additions & 0 deletions images/nginx/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FROM nginx
ADD nginx.conf /etc/nginx/conf.d/default.conf
18 changes: 18 additions & 0 deletions images/nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
server {
listen 80;
root /var/www/html/app/public;
index index.php index.htm index.html;

location / {
try_files $uri $uri/ /index.php?$query_string;
}

location /index.php {
include fastcgi_params;
fastcgi_connect_timeout 10s;
fastcgi_read_timeout 10s;
fastcgi_buffers 256 4k;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass php:9000;
}
}
3 changes: 3 additions & 0 deletions images/php/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM php:7.2-fpm-alpine
# lumen packages
RUN docker-php-ext-install mbstring tokenizer mysqli pdo_mysql
15 changes: 15 additions & 0 deletions images/php/app/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

[*.{yml,yaml}]
indent_size = 2
19 changes: 19 additions & 0 deletions images/php/app/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
APP_NAME=Lumen
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
APP_TIMEZONE=UTC

LOG_CHANNEL=stack
LOG_SLACK_WEBHOOK_URL=

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

CACHE_DRIVER=file
QUEUE_CONNECTION=sync
5 changes: 5 additions & 0 deletions images/php/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/vendor
/.idea
Homestead.json
Homestead.yaml
.env
9 changes: 9 additions & 0 deletions images/php/app/.styleci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
php:
preset: laravel
enabled:
- alpha_ordered_imports
disabled:
- length_ordered_imports
- unused_use
js: true
css: true
33 changes: 33 additions & 0 deletions images/php/app/app/Album.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Album extends Model
{

protected $table = 'albums';

protected $primaryKey = 'id';

public $incrementing = true;

public $timestamps = true;

protected $fillable = [
'title', 'description', 'user_id'
];

public function photos()
{
return $this->hasMany('App\AlbumPhoto', 'album_id');
}

public function user()
{
return $this->belongsTo('App\User');
}


}
27 changes: 27 additions & 0 deletions images/php/app/app/AlbumPhoto.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class AlbumPhoto extends Model
{

protected $table = 'album_photos';

protected $primaryKey = array('album_id', 'photo_id');

public $incrementing = false;

public $timestamps = true;

public function photo()
{
return $this->hasOne('App\Photo');
}

public function album()
{
return $this->hasOne('App\Album');
}
}
Empty file.
29 changes: 29 additions & 0 deletions images/php/app/app/Console/Kernel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Laravel\Lumen\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
//'App\Console\Commands\KeyGenerateCommand',
];

/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
//
}
}
10 changes: 10 additions & 0 deletions images/php/app/app/Events/Event.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace App\Events;

use Illuminate\Queue\SerializesModels;

abstract class Event
{
use SerializesModels;
}
16 changes: 16 additions & 0 deletions images/php/app/app/Events/ExampleEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace App\Events;

class ExampleEvent extends Event
{
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{
//
}
}
Loading