Initial commit to new repo

This commit is contained in:
Jonny Barnes 2016-05-19 15:01:28 +01:00
commit a5173c981b
292 changed files with 17472 additions and 0 deletions

52
.env.example Normal file
View file

@ -0,0 +1,52 @@
APP_ENV=local
APP_DEBUG=true
APP_KEY=SomeRandomString
APP_TIMEZONE=UTC
APP_LANG=en
APP_LOG=daily
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
DB_CONNECTION=pgsql
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=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAILGUN_DOMAIN=null
MAILGUN_SECRET=null
AWS_S3_KEY=your-key
AWS_S3_SECRET=your-secret
AWS_S3_REGION=region
AWS_S3_BUCKET=your-bucket
AWS_S3_URL=https://xxxxxxx.s3-region.amazonaws.com
APP_URL=https://example.com
APP_LONGURL=example.com
APP_SHORTURL=examp.le
ADMIN_USER=admin
ADMIN_PASS=password
PIWIK_URL=
PIWIK_SITE_ID=
TWITTER_CONSUMER_KEY=
TWITTER_CONSUMER_SECRET=
TWITTER_ACCESS_TOKEN=
TWITTER_ACCESS_TOKEN_SECRET=

11
.env.travis Normal file
View file

@ -0,0 +1,11 @@
APP_ENV=testing
APP_KEY=
APP_URL=http://localhost:8000
APP_LONGURL=localhost
APP_SHORTURL=local
DB_CONNECTION=travis
CACHE_DRIVER=array
SESSION_DRIVER=array
QUEUE_DRIVER=sync

3
.gitattributes vendored Normal file
View file

@ -0,0 +1,3 @@
* text=auto
*.css linguist-vendored
*.scss linguist-vendored

11
.gitignore vendored Normal file
View file

@ -0,0 +1,11 @@
/vendor
/node_modules
/bower_components
/public/storage
Homestead.yaml
Homestead.json
.env
/.sass-cache
/public/files
/public/keybase.txt
/coverage

7
.styleci.yml Normal file
View file

@ -0,0 +1,7 @@
preset: laravel
disabled:
- concat_without_spaces
finder:
path: app/

31
.travis.yml Normal file
View file

@ -0,0 +1,31 @@
language: php
sudo: false
addons:
postgresql: "9.4"
services:
- postgresql
php:
- 7.0
- nightly
matrix:
allow_failures:
- php: nightly
before_script:
- psql -U travis -c 'create database travis_ci_test'
- psql -U travis -d travis_ci_test -c 'create extension postgis'
- cp .env.travis .env
- travis_retry composer self-update --preview
- travis_retry composer install --no-interaction
- php artisan key:generate
- php artisan migrate
- php artisan db:seed
- php artisan serve &
- sleep 5 # Give artisan some time to start serving
script:
- phpdbg -qrr vendor/bin/phpunit --coverage-text

148
app/Article.php Normal file
View file

@ -0,0 +1,148 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Jonnybarnes\UnicodeTools\UnicodeTools;
use League\CommonMark\CommonMarkConverter;
use MartinBean\Database\Eloquent\Sluggable;
use Illuminate\Database\Eloquent\SoftDeletes;
class Article extends Model
{
use SoftDeletes;
/*
* We want to turn the titles into slugs
*/
use Sluggable;
const DISPLAY_NAME = 'title';
const SLUG = 'titleurl';
/**
* The attributes that should be mutated to dates.
*
* @var array
*/
protected $dates = ['deleted_at'];
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'articles';
/**
* Define the relationship with webmentions.
*
* @var array
*/
public function webmentions()
{
return $this->morphMany('App\WebMention', 'commentable');
}
/**
* We shall set a blacklist of non-modifiable model attributes.
*
* @var array
*/
protected $guarded = ['id'];
/**
* Process the article for display.
*
* @return string
*/
public function getMainAttribute($value)
{
$unicode = new UnicodeTools();
$markdown = new CommonMarkConverter();
$html = $markdown->convertToHtml($unicode->convertUnicodeCodepoints($value));
//change <pre><code>[lang] ~> <pre><code data-language="lang">
$match = '/<pre><code>\[(.*)\]\n/';
$replace = '<pre><code class="language-$1">';
$text = preg_replace($match, $replace, $html);
$default = preg_replace('/<pre><code>/', '<pre><code class="language-markdown">', $text);
return $default;
}
/**
* Convert updated_at to W3C time format.
*
* @return string
*/
public function getW3cTimeAttribute()
{
return $this->updated_at->toW3CString();
}
/**
* Convert updated_at to a tooltip appropriate format.
*
* @return string
*/
public function getTooltipTimeAttribute()
{
return $this->updated_at->toRFC850String();
}
/**
* Convert updated_at to a human readable format.
*
* @return string
*/
public function getHumanTimeAttribute()
{
return $this->updated_at->diffForHumans();
}
/**
* Get the pubdate value for RSS feeds.
*
* @return string
*/
public function getPubdateAttribute()
{
return $this->updated_at->toRSSString();
}
/**
* A link to the article, i.e. `/blog/1999/12/25/merry-christmas`.
*
* @return string
*/
public function getLinkAttribute()
{
return '/blog/' . $this->updated_at->year . '/' . $this->updated_at->format('m') . '/' . $this->titleurl;
}
/**
* Scope a query to only include articles from a particular year/month.
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeDate($query, $year = null, $month = null)
{
if ($year == null) {
return $query;
}
$start = $year . '-01-01 00:00:00';
$end = ($year + 1) . '-01-01 00:00:00';
if (($month !== null) && ($month !== '12')) {
$start = $year . '-' . $month . '-01 00:00:00';
$end = $year . '-' . ($month + 1) . '-01 00:00:00';
}
if ($month === '12') {
$start = $year . '-12-01 00:00:00';
//$end as above
}
return $query->where([
['updated_at', '>=', $start],
['updated_at', '<', $end],
]);
}
}

22
app/Client.php Normal file
View file

@ -0,0 +1,22 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Client extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'clients';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['client_url', 'client_name'];
}

View file

@ -0,0 +1,33 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Foundation\Inspiring;
class Inspire extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'inspire';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Display an inspiring quote';
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->comment(PHP_EOL.Inspiring::quote().PHP_EOL);
}
}

30
app/Console/Kernel.php Normal file
View file

@ -0,0 +1,30 @@
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
// Commands\Inspire::class,
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')
// ->hourly();
}
}

22
app/Contact.php Normal file
View file

@ -0,0 +1,22 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'contacts';
/**
* We shall set a blacklist of non-modifiable model attributes.
*
* @var array
*/
protected $guarded = ['id'];
}

8
app/Events/Event.php Normal file
View file

@ -0,0 +1,8 @@
<?php
namespace App\Events;
abstract class Event
{
//
}

View file

@ -0,0 +1,87 @@
<?php
namespace App\Exceptions;
use Exception;
use Illuminate\Validation\ValidationException;
use Illuminate\Session\TokenMismatchException;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
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 $exc
* @return void
*/
public function report(Exception $exc)
{
parent::report($exc);
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exc
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $exc)
{
if (config('app.debug')) {
return $this->renderExceptionWithWhoops($exc);
}
if ($exc instanceof ModelNotFoundException) {
$exc = new NotFoundHttpException($exc->getMessage(), $exc);
}
if ($exc instanceof TokenMismatchException) {
return redirect()->back()
->withInput($request->except('password', '_token'))
->withErrors('Validation Token has expired. Please try again', 'csrf');
}
return parent::render($request, $exc);
}
/**
* Render an exception using Whoops.
*
* @param \Exception $exc
* @return \Illuminate\Http\Response
*/
protected function renderExceptionWithWhoops(Exception $exc)
{
$whoops = new \Whoops\Run;
$handler = new \Whoops\Handler\PrettyPageHandler();
$handler->setEditor(function ($file, $line) {
return "atom://open?file=$file&line=$line";
});
$whoops->pushHandler($handler);
return new \Illuminate\Http\Response(
$whoops->handleException($exc),
$exc->getStatusCode(),
$exc->getHeaders()
);
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace App\Exceptions;
use Exception;
class RemoteContentNotFound extends Exception
{
//used when guzzle can’t find the remote content
}

View file

@ -0,0 +1,35 @@
<?php
namespace App\Http\Controllers;
class AdminController extends Controller
{
/*
|--------------------------------------------------------------------------
| Admin Controller
|--------------------------------------------------------------------------
|
| Here we have the logic for the admin cp
|
*/
/**
* Set variables.
*
* @var string
*/
public function __construct()
{
$this->username = env('ADMIN_USER');
}
/**
* Show the main admin CP page.
*
* @return \Illuminate\View\Factory view
*/
public function showWelcome()
{
return view('admin.welcome', ['name' => $this->username]);
}
}

View file

@ -0,0 +1,140 @@
<?php
namespace App\Http\Controllers;
use App\Article;
use Illuminate\Http\Request;
class ArticlesAdminController extends Controller
{
/**
* Show the new article form.
*
* @return \Illuminate\View\Factory view
*/
public function newArticle()
{
$message = session('message');
return view('admin.newarticle', ['message' => $message]);
}
/**
* List the articles that can be edited.
*
* @return \Illuminate\View\Factory view
*/
public function listArticles()
{
$posts = Article::select('id', 'title', 'published')->orderBy('id', 'desc')->get();
return view('admin.listarticles', ['posts' => $posts]);
}
/**
* Show the edit form for an existing article.
*
* @param string The article id
* @return \Illuminate\View\Factory view
*/
public function editArticle($articleId)
{
$post = Article::select(
'title',
'main',
'url',
'published'
)->where('id', $articleId)->get();
return view('admin.editarticle', ['id' => $articleId, 'post' => $post]);
}
/**
* Show the delete confirmation form for an article.
*
* @param string The article id
* @return \Illuminate\View\Factory view
*/
public function deleteArticle($articleId)
{
return view('admin.deletearticle', ['id' => $articleId]);
}
/**
* Process an incoming request for a new article and save it.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\View\Factory view
*/
public function postNewArticle(Request $request)
{
$published = $request->input('published');
if ($published == null) {
$published = '0';
}
//if a `.md` is attached use that for the main content.
$content = null; //set default value
if ($request->hasFile('article')) {
$file = $request->file('article')->openFile();
$content = $file->fread($file->getSize());
}
$main = $content ?? $request->input('main');
try {
$article = Article::create(
[
'url' => $request->input('url'),
'title' => $request->input('title'),
'main' => $main,
'published' => $published,
]
);
} catch (Exception $e) {
$msg = $e->getMessage();
$unique = strpos($msg, '1062');
if ($unique !== false) {
//We've checked for error 1062, i.e. duplicate titleurl
return redirect('admin/blog/new')->withInput()->with('message', 'Duplicate title, please change');
}
//this isn't the error you're looking for
throw $e;
}
return view('admin.newarticlesuccess', ['id' => $article->id, 'title' => $article->title]);
}
/**
* Process an incoming request to edit an article.
*
* @param string
* @param \Illuminate\Http\Request $request
* @return \Illuminate|View\Factory view
*/
public function postEditArticle($articleId, Request $request)
{
$published = $request->input('published');
if ($published == null) {
$published = '0';
}
$article = Article::find($articleId);
$article->title = $request->input('title');
$article->url = $request->input('url');
$article->main = $request->input('main');
$article->published = $published;
$article->save();
return view('admin.editarticlesuccess', ['id' => $articleId]);
}
/**
* Process a request to delete an aricle.
*
* @param string The article id
* @return \Illuminate\View\Factory view
*/
public function postDeleteArticle($articleId)
{
Article::where('id', $articleId)->delete();
return view('admin.deletearticlesuccess', ['id' => $articleId]);
}
}

View file

@ -0,0 +1,69 @@
<?php
namespace App\Http\Controllers;
use App\Article;
use Illuminate\Http\Response;
use Jonnybarnes\IndieWeb\Numbers;
class ArticlesController extends Controller
{
/**
* Show all articles (with pagination).
*
* @return \Illuminate\View\Factory view
*/
public function showAllArticles($year = null, $month = null)
{
$articles = Article::where('published', '1')
->date($year, $month)
->orderBy('updated_at', 'desc')
->simplePaginate(5);
return view('multipost', ['data' => $articles]);
}
/**
* Show a single article.
*
* @return \Illuminate\View\Factory view
*/
public function singleArticle($year, $month, $slug)
{
$article = Article::where('titleurl', $slug)->first();
if ($article->updated_at->year != $year || $article->updated_at->month != $month) {
throw new \Exception;
}
return view('singlepost', ['article' => $article]);
}
/**
* We only have the ID, work out post title, year and month
* and redirect to it.
*
* @return \Illuminte\Routing\RedirectResponse redirect
*/
public function onlyIdInUrl($inURLId)
{
$numbers = new Numbers();
$realId = $numbers->b60tonum($inURLId);
$article = Article::findOrFail($realId);
return redirect($article->link);
}
/**
* Returns the RSS feed.
*
* @return \Illuminate\Http\Response
*/
public function makeRSS()
{
$articles = Article::where('published', '1')->orderBy('updated_at', 'desc')->get();
$buildDate = $articles->first()->updated_at->toRssString();
$contents = (string) view('rss', ['articles' => $articles, 'buildDate' => $buildDate]);
return (new Response($contents, '200'))->header('Content-Type', 'application/rss+xml');
}
}

View file

@ -0,0 +1,72 @@
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
class AuthController extends Controller
{
/*
|--------------------------------------------------------------------------
| Registration & Login Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users, as well as the
| authentication of existing users. By default, this controller uses
| a simple trait to add these behaviors. Why don't you explore it?
|
*/
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
/**
* Where to redirect users after login / registration.
*
* @var string
*/
protected $redirectTo = '/';
/**
* Create a new authentication controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware($this->guestMiddleware(), ['except' => 'logout']);
}
/**
* Get a validator for an incoming registration request.
*
* @param array $data
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
]);
}
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
}

View file

@ -0,0 +1,32 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
class PasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset requests
| and uses a simple trait to include this behavior. You're free to
| explore this trait and override any methods you wish to tweak.
|
*/
use ResetsPasswords;
/**
* Create a new password controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
}

View file

@ -0,0 +1,29 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class AuthController extends Controller
{
/**
* Log in a user, set a sesion variable, check credentials against
* the .env file.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Routing\RedirectResponse redirect
*/
public function login(Request $request)
{
if ($request->input('username') === env('ADMIN_USER')
&&
$request->input('password') === env('ADMIN_PASS')
) {
session(['loggedin' => true]);
return redirect()->intended('admin');
}
return redirect()->route('login');
}
}

Some files were not shown because too many files have changed in this diff Show more