Skip to content

Commit

Permalink
laravel-vuejs
Browse files Browse the repository at this point in the history
  • Loading branch information
amrbedair committed Sep 16, 2017
1 parent 3c0635e commit a46f145
Show file tree
Hide file tree
Showing 83 changed files with 7,669 additions and 1 deletion.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ <h3 >Laravel + Vue.js</h3>
<p>SPA using Vue.js for frontend, and Laravel micro-framework "Lumen" for back end.</p>
<p>Please not I am not using lot of feature like server side rendering, and single file component, for simplicity purposes</p>
<p>Also I am not using TypeScript although I am big fan of it for the same reason</p>
<p><a href="#" class="btn btn-danger btn-lg" role="button">Go</a></p>
<p><a href="laravel-vuejs/frontend" class="btn btn-danger btn-lg" role="button">Go</a></p>
</div>
<div class="col-sm-4">
<h3 >Vue.js</h3>
Expand Down
28 changes: 28 additions & 0 deletions laravel-vuejs/backend/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
APP_NAME=daleel
APP_ENV=local
APP_KEY=base64:vMkAD5CwHbGMRIEJW7JGfmXV9qTj5my88tep1iQT1Q0=
APP_DEBUG=true
APP_LOG_LEVEL=debug
APP_URL=http://daft.nefya.com/laravel-vuejs/backend/public

BREWERY_DB_API_KEY=985aeddea212aa71cac6e71dc675ea57

BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
1 change: 1 addition & 0 deletions laravel-vuejs/backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
vendor
Empty file added laravel-vuejs/backend/README.md
Empty file.
Empty file.
29 changes: 29 additions & 0 deletions laravel-vuejs/backend/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 = [
//
];

/**
* 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 laravel-vuejs/backend/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 laravel-vuejs/backend/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()
{
//
}
}
50 changes: 50 additions & 0 deletions laravel-vuejs/backend/app/Exceptions/Handler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Validation\ValidationException;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Laravel\Lumen\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\HttpException;

class Handler extends ExceptionHandler
{
/**
* A list of the exception types that should not be reported.
*
* @var array
*/
protected $dontReport = [
AuthorizationException::class,
HttpException::class,
ModelNotFoundException::class,
ValidationException::class,
];

/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* @param \Exception $e
* @return void
*/
public function report(Exception $e)
{
parent::report($e);
}

/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
return parent::render($request, $e);
}
}
163 changes: 163 additions & 0 deletions laravel-vuejs/backend/app/Helpers/BreweryDbHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
<?php

namespace App\Helpers;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

require_once base_path("/lib/Pintlabs/Service/Brewerydb/Exception.php");
require_once base_path("/lib/Pintlabs/Service/Brewerydb.php");

class BreweryDbHelper {

private $bdb;
private $styles = [];

public function __construct() {

$this->bdb = new \Pintlabs_Service_Brewerydb(env('BREWERY_DB_API_KEY'));
$this->bdb->setFormat('php');

$this->init();
}

private function init() {

// try to get styles from the cache
$this->styles = Cache::get('styles');
if(!$this->styles) {

$result = $this->request('styles');
$this->styles = $result['data'];
/**
* cache it for 24 hours, maybe we need more!
* it depends on how often new style may be added
* default chache in php is FileCache, we may use memcache or
* anything else, but this is enough for simplicity
*/
Cache::put('styles', $this->styles, 60 * 60 * 24);
}
}

private function request($endpoint, $params=[], $method='GET') {
try {
$result = $this->bdb->request($endpoint, $params, $method);
if($result['status'] == 'failure') {
abort(500, $result['errorMessage']);
}
return $result;
} catch (Exception $e) {
// log
Log::error('[ERR-00] Error while trying to access '.$endpoint.' endpoint '.$e->getMessage());
abort(500, $e->getMessage());
}
}

public function getRandomBeer() {

/**
* if empty for any reason like failed while constructing the
* singleton instance .. try one more time
*/
if(empty($this->styles)) {
$this->init();
}

/**
* still empty ... just log and return null
* we may use hardcoded style id, if we are sure it will not go away!
*/
if(empty($this->styles)) {
Log::error('[ERR-02] Empty style list!');
return null;
}

while(true) {
$randomStyle = $this->styles[array_rand($this->styles)];
$result = $this->request('beers', [
'styleId' => $randomStyle['id'],
'order' => 'random',
'randomCount' => 1,
'withBreweries' => 'Y',
]);

if(!isset($result['data'])) {
Log::error('[ERR-03] Error retreiving data '.$result['errorMessage']);
return null;
}

$data = $result['data'];
if( count($data) < 1 || // it may happen!
!isset($data[0]['labels']) ||
!isset($data[0]['description']) ) {
continue;
}
return $data[0];
}
}

public function search($q='', $type='beer', $breweryId='', $page=1) {

if(empty($q)) return[];

$beers = [];

if($type == 'beer') { // TYPE_BEER
$result = $this->request('search', [
'p' => $page,
'q' => $q,
'type' => 'beer',
]);
if(isset($result['data'])) {
$this->mergeValidBeers($beers, $result['data']);
}

} else { // TYPE_BREWERY

$breweryIds = empty($breweryId) ? [] :[$breweryId];

if(empty($breweryId)) {
// get brewery id first
$result = $this->request('search', [
'q' => $q,
'type' => 'brewery',
]);

// check valid result
if(isset($result['data']) && is_array($result['data'])) {
$breweries = $result['data'];
foreach ($breweries as $brewery) { $breweryIds[] = $brewery['id']; }
}
}

if(!empty($breweryIds)) {
foreach ($breweryIds as $breweryId) {
// check if already cached
$result = Cache::get("BREWERY_".$breweryId."_RESULT");
if(!$result) {
$result = $this->request("/brewery/$breweryId/beers");
Cache::put("BREWERY_".$breweryId."_RESULT", $result, 60 * 60 * 24);
}
if(!isset($result['data'])) continue;
$this->mergeValidBeers($beers, $result['data']);
}
}
}

return $beers;
}

/**
* skip beers with no labels or description
* @param array $array
* @param array $beers
*/
private function mergeValidBeers(&$array, $beers) {
foreach ($beers as $beer) {
if(!isset($beer['labels']) || !isset($beer['description'])) {
continue;
}
$array[] = $beer;
}
}
}
48 changes: 48 additions & 0 deletions laravel-vuejs/backend/app/Http/Controllers/ApiController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;

class ApiController extends Controller {

public function getRandomBeer(Request $request) {

// return response('{"type":"success","beer":{"id":"GUpvks","name":"Tume","nameDisplay":"Tume","description":"An old style dark lager. Brewed since 1960.\r\nSaku Tume is special dark brew with an excellent dark colouring and rich taste. For the preparation of Saku Tume, in addition to pilsner malt, Munich and caramel malt, as well as sugar. A long lager period ensures a balanced taste and fragrance bouquet for Saku Tume.","abv":"6.7","styleId":88,"isOrganic":"Y","labels":{"icon":"https:\/\/s3.amazonaws.com\/brewerydbapi\/beer\/GUpvks\/upload_OemBKY-icon.png","medium":"https:\/\/s3.amazonaws.com\/brewerydbapi\/beer\/GUpvks\/upload_OemBKY-medium.png","large":"https:\/\/s3.amazonaws.com\/brewerydbapi\/beer\/GUpvks\/upload_OemBKY-large.png"},"status":"verified","statusDisplay":"Verified","createDate":"2015-07-29 21:03:30","updateDate":"2015-12-18 04:28:09","style":{"id":88,"categoryId":7,"category":{"id":7,"name":"European-germanic Lager","createDate":"2012-03-21 20:06:46"},"name":"Traditional German-Style Bock","shortName":"Bock","description":"Traditional bocks are made with all malt and are strong, malty, medium- to full-bodied, bottom-fermented beers with moderate hop bitterness that should increase proportionately with the starting gravity. Malt character should be a balance of sweetness and toasted\/nut-like malt; not caramel. Hop flavor should be low and hop aroma should be very low. Bocks can range in color from deep copper to dark brown. Fruity esters should be minimal. Diacetyl should be absent.","ibuMin":"20","ibuMax":"30","abvMin":"6.3","abvMax":"7.5","srmMin":"20","srmMax":"30","ogMin":"1.066","fgMin":"1.018","fgMax":"1.024","createDate":"2012-03-21 20:06:46","updateDate":"2015-04-07 15:38:54"},"breweries":[{"id":"80ewUQ","name":"Saku \u00d5lletehas","nameShortDisplay":"Saku \u00d5lletehas","description":"The brewing traditions of Saku Brewery reach back to the beginning of the 19th century. Then the Saku estate was owned by count Karl Friedrich Rehbinder who built a distillery and a brewery on his estate. The brewery was first documented in October 1820. It is believed that the production of beer, for the purpose of sale to pubs and taverns begun during the autumn of that year. From the end of 19th century onward Saku has remained among the leading breweries in Estonia.\r\nIn 1991 joint venture Saku \u00d5lletehas was established. Since January 27, 1998 the shares of Saku Brewery were traded in the list on the Tallinn Stock Exchange. On September 20, 2008, the shares of Saku \u00d5lletehase AS were delisted from Tallinn Stock Exchange. Today 100% of the shares are owned by Carlsberg Breweries.\r\nThrough large investments, Saku Brewery has become the market leader on the Estonian beer market. According to market research by ACNielsen in March 2009, Saku Brewery held 38,7% of the local market share. The total sales of beer by Saku amounted to 59 million litres in 2007.\r\nBeverages of Saku Brewery are exported amongst other countries to Sweden (the only Estonian beer in the Systembolaget is Saku Kuld), Finland, Netherlands, England, Germany, Ireland and Canada. Saku\'s exports during the first five months of 2009 amounted to 3,12 million litres.","website":"http:\/\/www.saku.ee\/","established":"1820","isOrganic":"N","status":"verified","statusDisplay":"Verified","createDate":"2012-01-03 02:42:07","updateDate":"2015-12-22 14:56:47","isMassOwned":"N","brandClassification":"craft","locations":[{"id":"CgUpen","name":"Main Brewery","streetAddress":"Tallinna mnt.2","locality":"Saku","region":"Harjumaa","postalCode":"75501","phone":"+3726508400","website":"http:\/\/www.saku.ee\/","latitude":59.3014407,"longitude":24.6679157,"isPrimary":"Y","inPlanning":"N","isClosed":"N","openToPublic":"Y","locationType":"micro","locationTypeDisplay":"Micro Brewery","countryIsoCode":"EE","yearOpened":"1820","status":"verified","statusDisplay":"Verified","createDate":"2012-01-03 02:42:07","updateDate":"2014-07-23 19:11:34","country":{"isoCode":"EE","name":"ESTONIA","displayName":"Estonia","isoThree":"EST","numberCode":233,"createDate":"2012-01-03 02:41:33"}}]}]}}')->header('Content-Type', 'application/json');

$app= App::getFacadeRoot();
$breweryDbHelper = $app->make('breweryDbHelper');
$beer = $breweryDbHelper->getRandomBeer();

return [
'type' => 'success',
'beer' => $beer,
];
}

public function search(Request $request) {

$app= App::getFacadeRoot();
$breweryDbHelper = $app->make('breweryDbHelper');
$beers = $breweryDbHelper->search(
$request->input('term'),
$request->input('type'),
$request->input('breweryId')
);
return [
'type' => 'success',
'beers' => $beers,
];
}

public function flushCache(Request $request) {
Cache::flush();
return [
'type' => 'success',
'message' => 'Cache flushed successfully',
];
}

}
10 changes: 10 additions & 0 deletions laravel-vuejs/backend/app/Http/Controllers/Controller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace App\Http\Controllers;

use Laravel\Lumen\Routing\Controller as BaseController;

class Controller extends BaseController
{
//
}
Loading

0 comments on commit a46f145

Please sign in to comment.