FEATURE #1427: add homepage functionality.

Displaying homepage now depends on module handler
This commit is contained in:
Michal Kváček
2016-02-17 13:24:16 +01:00
parent 6d0e6e26f6
commit 37a698b631
15 changed files with 329 additions and 38 deletions
+3
View File
@@ -1,3 +1,6 @@
/resources/views/modules
**/views/**/custom/*
!**/views/**/custom/.gitkeep
/public/uploads/* /public/uploads/*
!/public/uploads/.gitkeep !/public/uploads/.gitkeep
/resources/views/vendor /resources/views/vendor
+42
View File
@@ -0,0 +1,42 @@
<?php
namespace App\Helpers;
use Symfony\Component\Process\Exception\InvalidArgumentException;
class Template
{
/**
* Getter for real template name
*
* @param $template
*
* @return null|string
*/
public static function name($template)
{
$namespace = null;
if (strpos($template, '::')) {
list($namespace, $template) = explode('::', $template);
}
$theme = config('app.theme');
// list of prefixes
$prefixes = [$theme . '.custom.', $theme . '.', ''];
$view = null;
foreach ($prefixes as $prefix) {
if (view()->exists($namespace . 'visitor.' . $prefix . $template)) {
$view = $namespace . 'visitor.' . $prefix . $template;
break;
}
}
if (is_null($view)) {
throw new InvalidArgumentException('Cannot find template for ' . $namespace . $template);
}
return $view;
}
}
+9 -7
View File
@@ -2,10 +2,11 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs; use App\Helpers\Template;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController class Controller extends BaseController
{ {
@@ -16,15 +17,16 @@ class Controller extends BaseController
* *
* This method will be used for switching among templates. * This method will be used for switching among templates.
* *
* @todo add template support * @param $template
*
* @param null $view
* @param array $data * @param array $data
* @param array $mergeData * @param array $mergeData
* *
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/ */
protected function view($view = null, $data = [], $mergeData = []) { public static function VisitorsView($template, $data = [], $mergeData = [])
{
$view = Template::name($template);
return view($view, $data, $mergeData); return view($view, $data, $mergeData);
} }
} }
+20 -4
View File
@@ -9,11 +9,28 @@ use Illuminate\Support\Facades\Auth;
class ContentPage extends Controller class ContentPage extends Controller
{ {
/**
* @var Content
*/
protected $content;
/**
* @param Content $content
*/
function __construct(Content $content)
{
$this->content = $content;
}
public function getPage($url) public function getPage($url)
{ {
$page = Content::where('url', $url) $page = $this->content->getByURL($url);
->where('status', '!=', Content::STATUS_DELETED)
->first(); // no page available
if (!$page) {
abort(404);
}
return $this->renderPage($page); return $this->renderPage($page);
} }
@@ -38,6 +55,5 @@ class ContentPage extends Controller
// render page // render page
return $handler->render($page, ''); return $handler->render($page, '');
// return call_user_func([$handler, 'render'], $page);
} }
} }
+7 -7
View File
@@ -3,24 +3,24 @@
namespace App\Http\Controllers\Visitor; namespace App\Http\Controllers\Visitor;
use App\Http\Requests; use App\Http\Requests;
use App\Models\Content;
use Symfony\Component\Process\Exception\InvalidArgumentException;
class Homepage extends ContentPage class Homepage extends ContentPage
{ {
public function getIndex() public function getIndex()
{ {
// try to find some homepage // try to find some homepage
$page = Content::where('is_homepage', 1) $page = $this->content->getHomepage();
->where('status', '!=', Content::STATUS_DELETED)
->first();
// test if we have any homepage // test if we have any homepage
if (!$page) { if (!$page) {
throw new InvalidArgumentException('Cannot load home page!'); return view('errors.homepageNotAvailable');
} }
// render page // render page
return $this->renderPage($page); try {
return $this->renderPage($page);
} catch (\Exception $e) {
return view('errors.homepageNotAvailable');
}
} }
} }
+28 -15
View File
@@ -4,21 +4,8 @@
* This routing groups is used for routing along public part of website * This routing groups is used for routing along public part of website
*/ */
Route::group(['middleware' => ['web']], function () { Route::pattern('id', '\d+');
Route::pattern('url', '[0-9\-a-z]+');
Route::get('/', 'Visitor\Homepage@getIndex')
->name('page.index');
// display login form
Route::get('login', function () {
return view('admin.loginForm.form');
})
->name('loginForm');
// handle login
Route::post('login', 'Admin\Login@postLogin')
->name('login');
});
/*******************************************************************************/ /*******************************************************************************/
@@ -193,3 +180,29 @@ Route::group([
}) })
->name('logout'); ->name('logout');
}); });
/**************************************************************************************/
/**
* This section must be specified as last one
*/
Route::group(['middleware' => ['web']], function () {
Route::get('', 'Visitor\Homepage@getIndex')
->name('page.index');
// display login form
Route::get('login', function () {
return view('admin.loginForm.form');
})
->name('loginForm');
// handle login
Route::post('login', 'Admin\Login@postLogin')
->name('login');
// route for all content pages. This rule must be specified last (because it matches every route)
Route::get('{url}', 'Visitor\ContentPage@getPage')
->name('page.content');
});
+35
View File
@@ -31,6 +31,41 @@ class Content extends Model
const STATUS_PROTECTED = 'protected'; const STATUS_PROTECTED = 'protected';
const STATUS_PUBLIC = 'public'; const STATUS_PUBLIC = 'public';
/**
* Getter for query with setup filter for non-deleted and non-draft pages
*/
protected function getPageQuery()
{
return Content::where('status', '!=', Content::STATUS_DELETED)
->where('status', '!=', Content::STATUS_DRAFT);
}
/**
* Getter for homepage content page
*
* @return Content
*/
public function getHomepage()
{
return $this->getPageQuery()
->where('is_homepage', 1)
->first();
}
/**
* Getter for any page specified by its url.
*
* @param $url
*
* @return Content
*/
public function getByURL($url)
{
return $this->getPageQuery()
->where('url', $url)
->first();
}
/** /**
* Getter for overview of all content pages of given handler (module type) * Getter for overview of all content pages of given handler (module type)
* *
+11 -5
View File
@@ -16,6 +16,14 @@ class GlobalViewDataProvider extends ServiceProvider
{ {
view()->share('vendorName', 'ja s.r.o.'); view()->share('vendorName', 'ja s.r.o.');
// extend Blade "@extends" macro - with this macro allows to use "hierarchy" in templates
Blade::extend(function ($view) {
$pattern = $this->createPattern('extendVisitor');
$code = '@extends(\App\Helpers\Template::name($2))';
return preg_replace($pattern, $code, $view);
});
// register extension for rendering widget areas // register extension for rendering widget areas
Blade::extend(function ($view) { Blade::extend(function ($view) {
$pattern = $this->createPattern('widgetArea'); $pattern = $this->createPattern('widgetArea');
@@ -37,11 +45,8 @@ class GlobalViewDataProvider extends ServiceProvider
?> ?>
'; ';
return preg_replace($pattern, $code, $view); return preg_replace($pattern, $code, $view);
}); });
} }
/** /**
@@ -51,8 +56,9 @@ class GlobalViewDataProvider extends ServiceProvider
* *
* @return string * @return string
*/ */
private function createPattern($function){ private function createPattern($function)
return '/(?<!\w)(\s*)@'.$function.'\(\s*(.*)\)/'; {
return '/(?<!\w)(\s*)@' . $function . '\(\s*(.*)\)/';
} }
/** /**
+2
View File
@@ -97,6 +97,8 @@ return [
*/ */
'upload_url' => env('UPLOAD_URL', PHP_SAPI === 'cli' ? '' : url('uploads')), 'upload_url' => env('UPLOAD_URL', PHP_SAPI === 'cli' ? '' : url('uploads')),
'thumbnail_url' => env('THUMBNAIL_URL', PHP_SAPI === 'cli' ? '' : url('uploads/thumbnails')), 'thumbnail_url' => env('THUMBNAIL_URL', PHP_SAPI === 'cli' ? '' : url('uploads/thumbnails')),
'theme' => 'default_theme',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Logging Configuration | Logging Configuration
+4
View File
@@ -0,0 +1,4 @@
<?php
return [
'welcome' => 'Welcome to my page'
];
@@ -0,0 +1,5 @@
@extendVisitor("errorLayout")
@section('content')
<div class="title">Home is not available at the moment.. Sorry for any inconvenience.</div>
@endsection
@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
@yield('head_meta')
<title>@yield('pageName', @trans('visitor/common.welcome')) | {{$vendorName}}</title>
<link rel="stylesheet" href="{{asset('../resources/assets/css/foundation.min.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/font-awesome.min.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/admin.css')}}" />
@yield('head_stylesheets')
<style>
html, body {
height: 100%;
}
body {
margin: 0;
padding: 0;
width: 100%;
color: #B0BEC5;
display: table;
}
.container {
text-align: center;
display: table-cell;
vertical-align: middle;
}
.content {
text-align: center;
display: inline-block;
}
.title {
font-size: 72px;
margin-bottom: 40px;
}
</style>
</head>
<body>
<div class="container">
<h1>Default theme template</h1>
<div class="content">
@yield('content')
</div>
</div>
</body>
</html>
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
@yield('head_meta')
<title>@yield('pageName', @trans('visitor/common.welcome')) | {{$vendorName}}</title>
<link rel="stylesheet" href="{{asset('../resources/assets/css/foundation.min.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/font-awesome.min.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/admin.css')}}" />
@yield('head_stylesheets')
<link href="https://fonts.googleapis.com/css?family=Lato:100" rel="stylesheet" type="text/css">
<style>
html, body {
height: 100%;
}
body {
margin: 0;
padding: 0;
width: 100%;
color: #B0BEC5;
display: table;
font-weight: 100;
font-family: 'Lato';
}
.container {
text-align: center;
display: table-cell;
vertical-align: middle;
}
.content {
text-align: center;
display: inline-block;
}
.title {
font-size: 72px;
margin-bottom: 40px;
}
</style>
</head>
<body>
<div class="container">
<div class="content">
@yield('content')
</div>
</div>
</body>
</html>
+55
View File
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
@yield('head_meta')
<title>@yield('pageName', @trans('visitor/common.welcome')) | {{$vendorName}}</title>
<link rel="stylesheet" href="{{asset('../resources/assets/css/foundation.min.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/font-awesome.min.css')}}" />
<link rel="stylesheet" href="{{asset('../resources/assets/css/admin.css')}}" />
@yield('head_stylesheets')
<link href="https://fonts.googleapis.com/css?family=Lato:100" rel="stylesheet" type="text/css">
<style>
html, body {
height: 100%;
}
body {
margin: 0;
padding: 0;
width: 100%;
color: #B0BEC5;
display: table;
font-weight: 100;
font-family: 'Lato';
}
.container {
text-align: center;
display: table-cell;
vertical-align: middle;
}
.content {
text-align: center;
display: inline-block;
}
.title {
font-size: 72px;
margin-bottom: 40px;
}
</style>
</head>
<body>
<div class="container">
<div class="content">
@yield('content')
</div>
</div>
</body>
</html>