├── app ├── commands │ └── .gitkeep ├── markdown │ ├── faq.md │ └── news.md ├── config │ ├── packages │ │ ├── .gitkeep │ │ └── artdarek │ │ │ └── oauth-4-laravel │ │ │ ├── .gitkeep │ │ │ └── config.php │ ├── compile.php │ ├── local │ │ ├── app.php │ │ └── database.php │ ├── testing │ │ ├── cache.php │ │ └── session.php │ ├── services.php │ ├── workbench.php │ ├── view.php │ ├── remote.php │ ├── auth.php │ ├── queue.php │ ├── cache.php │ ├── database.php │ ├── mail.php │ ├── session.php │ └── app.php ├── controllers │ ├── .gitkeep │ ├── BaseController.php │ ├── FeedController.php │ ├── VotesController.php │ ├── TagsController.php │ ├── SearchController.php │ ├── CommentsController.php │ ├── PagesController.php │ ├── SnippetsController.php │ └── UsersController.php ├── database │ ├── seeds │ │ ├── .gitkeep │ │ ├── VotesTableSeeder.php │ │ ├── DatabaseSeeder.php │ │ ├── SnippetsTableSeeder.php │ │ ├── CommentsTableSeeder.php │ │ └── UsersTableSeeder.php │ ├── migrations │ │ ├── .gitkeep │ │ ├── 2014_10_31_225054_create_tags_table.php │ │ ├── 2014_11_01_134754_create_snippets_title_fulltext_index.php │ │ ├── 2014_10_31_225259_create_taggables_table.php │ │ ├── 2014_10_25_122712_create_comments_table.php │ │ ├── 2014_10_24_124915_create_snippets_table.php │ │ ├── 2014_10_28_035857_enable_snippets_fulltext_search.php │ │ ├── 2014_10_26_042322_create_votes_table.php │ │ └── 2014_10_24_091019_create_users_table.php │ └── .gitignore ├── start │ ├── local.php │ ├── artisan.php │ └── global.php ├── storage │ ├── .gitignore │ ├── cache │ │ └── .gitignore │ ├── debugbar │ │ └── .gitignore │ ├── logs │ │ └── .gitignore │ ├── meta │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ └── views │ │ └── .gitignore ├── views │ ├── partials │ │ ├── paginator.blade.php │ │ ├── search_form.blade.php │ │ ├── tagcloud.blade.php │ │ ├── markdown_help.blade.php │ │ ├── comment_form.blade.php │ │ ├── tracking.blade.php │ │ ├── comment.blade.php │ │ ├── statistics.blade.php │ │ ├── snippet.blade.php │ │ ├── snippet_form.blade.php │ │ └── navbar.blade.php │ ├── pages │ │ ├── markdown.blade.php │ │ ├── sitemap.blade.php │ │ ├── feed.blade.php │ │ └── home.blade.php │ ├── snippets │ │ ├── create.blade.php │ │ ├── edit.blade.php │ │ ├── index.blade.php │ │ └── show.blade.php │ ├── errors │ │ ├── 404.blade.php │ │ └── 503.blade.php │ ├── comments │ │ └── edit.blade.php │ ├── search │ │ └── index.blade.php │ ├── users │ │ └── show.blade.php │ └── layouts │ │ └── main.blade.php ├── Vimrcfu │ ├── Facades │ │ └── TextFacade.php │ ├── Validation │ │ ├── CommentValidator.php │ │ ├── SnippetValidator.php │ │ └── Validator.php │ ├── Providers │ │ ├── CoreServiceProvider.php │ │ └── PersistenceServiceProvider.php │ ├── Users │ │ ├── UsersRepository.php │ │ ├── EloquentUsersRepository.php │ │ └── User.php │ ├── Tags │ │ ├── Tag.php │ │ ├── TagsRepository.php │ │ └── EloquentTagsRepository.php │ ├── Comments │ │ ├── CommentsRepository.php │ │ ├── Comment.php │ │ └── EloquentCommentsRepository.php │ ├── Votes │ │ └── Vote.php │ ├── Exceptions │ │ └── ValidationException.php │ ├── Snippets │ │ ├── SnippetsRepository.php │ │ ├── Snippet.php │ │ └── EloquentSnippetsRepository.php │ └── Core │ │ └── Text.php ├── tests │ └── TestCase.php ├── lang │ └── en │ │ ├── pagination.php │ │ ├── reminders.php │ │ └── validation.php ├── routes.php └── filters.php ├── public ├── packages │ └── .gitkeep ├── robots.txt ├── favicon.ico ├── img │ └── home_bg.png ├── apple-touch-icon.png ├── fonts │ ├── FontAwesome.otf │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.ttf │ ├── fontawesome-webfont.woff │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ └── glyphicons-halflings-regular.woff ├── .htaccess ├── js │ ├── main.js │ ├── tagging.js │ ├── vendor │ │ ├── bootstrap-tagsinput.min.js.map │ │ ├── html5shiv.js │ │ ├── wow.min.js │ │ └── bootstrap-tagsinput.min.js │ └── snake.js ├── index.php └── css │ ├── main.css │ └── bootstrap-theme.min.css ├── .gitattributes ├── .gitignore ├── server.php ├── config.php_cs ├── phpunit.xml ├── composer.json ├── bootstrap ├── paths.php ├── start.php └── autoload.php ├── CONTRIBUTING.md ├── artisan └── README.md /app/commands/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/markdown/faq.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/markdown/news.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/config/packages/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/controllers/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/database/seeds/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/packages/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /app/database/migrations/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite 2 | -------------------------------------------------------------------------------- /app/start/local.php: -------------------------------------------------------------------------------- 1 | 2 | {{ $snippets->appends(['q' => Input::get('q')])->links() }} 3 | 4 | -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/florianbeer/vimrcfu/HEAD/public/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/florianbeer/vimrcfu/HEAD/public/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/florianbeer/vimrcfu/HEAD/public/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /app/Vimrcfu/Facades/TextFacade.php: -------------------------------------------------------------------------------- 1 | Search 2 | {{ Form::open(['route' => 'search', 'method' => 'get']) }} 3 |
4 | {{ Form::text('q', Input::get('q'), ['class' => 'form-control', 'placeholder' => 'Search', 'tabindex' => '1']) }} 5 |
6 | {{ Form::close() }} 7 | -------------------------------------------------------------------------------- /app/Vimrcfu/Validation/CommentValidator.php: -------------------------------------------------------------------------------- 1 | 'required|min:4' 12 | ]; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /app/Vimrcfu/Providers/CoreServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->bind('text', 'Vimrcfu\Core\Text'); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /app/views/pages/markdown.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.main') 2 | 3 | @section('title', $title) 4 | 5 | @section('content') 6 | 7 |
8 |
9 |
10 | {{ Text::renderInclude($file) }} 11 |
12 |
13 |
14 | 15 | @stop 16 | -------------------------------------------------------------------------------- /app/views/partials/tagcloud.blade.php: -------------------------------------------------------------------------------- 1 | @if(count($tags)) 2 | @if($title) 3 |

{{{ $title or 'Popular Tags' }}}

4 | @endif 5 | @foreach($tags as $i => $tag) 6 | {{{ $tag->name }}} 7 | @endforeach 8 | @endif 9 | -------------------------------------------------------------------------------- /app/Vimrcfu/Users/UsersRepository.php: -------------------------------------------------------------------------------- 1 | morphedByMany('Vimrcfu\Snippets\Snippet', 'taggable'); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /app/Vimrcfu/Validation/SnippetValidator.php: -------------------------------------------------------------------------------- 1 | 'required|min:4', 12 | 'body' => 'required', 13 | 'description' => 'required' 14 | ]; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /app/controllers/BaseController.php: -------------------------------------------------------------------------------- 1 | layout)) 13 | { 14 | $this->layout = View::make($this->layout); 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/Vimrcfu/Comments/CommentsRepository.php: -------------------------------------------------------------------------------- 1 | belongsTo('Vimrcfu\Users\User'); 11 | } 12 | 13 | public function snippet() 14 | { 15 | return $this->belongsTo('Vimrcfu\Snippets\Snippet'); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/Vimrcfu/Comments/Comment.php: -------------------------------------------------------------------------------- 1 | belongsTo('Vimrcfu\Snippets\Snippet'); 11 | } 12 | 13 | public function user() 14 | { 15 | return $this->belongsTo('Vimrcfu\Users\User'); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Redirect Trailing Slashes... 9 | RewriteRule ^(.*)/$ /$1 [L,R=301] 10 | 11 | # Handle Front Controller... 12 | RewriteCond %{REQUEST_FILENAME} !-d 13 | RewriteCond %{REQUEST_FILENAME} !-f 14 | RewriteRule ^ index.php [L] 15 | 16 | -------------------------------------------------------------------------------- /app/database/seeds/VotesTableSeeder.php: -------------------------------------------------------------------------------- 1 | $snippet->user_id, 14 | 'snippet_id' => $snippet->id, 15 | 'score' => 1 16 | ]); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/Vimrcfu/Users/EloquentUsersRepository.php: -------------------------------------------------------------------------------- 1 | $data['github_id']]); 12 | $user->fill($data); 13 | $user->save(); 14 | 15 | return $user; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/database/seeds/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | call('SnippetsTableSeeder'); 15 | $this->call('CommentsTableSeeder'); 16 | $this->call('VotesTableSeeder'); 17 | $this->call('UsersTableSeeder'); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /app/tests/TestCase.php: -------------------------------------------------------------------------------- 1 | 2 | You can use some markdown. 3 | 5 | 6 | -------------------------------------------------------------------------------- /app/config/compile.php: -------------------------------------------------------------------------------- 1 | true, 17 | 18 | ); 19 | -------------------------------------------------------------------------------- /app/database/seeds/SnippetsTableSeeder.php: -------------------------------------------------------------------------------- 1 | $faker->word, 16 | 'body' => $faker->paragraph, 17 | 'description' => $faker->paragraph, 18 | 'user_id' => $faker->randomElement([1,2,3]) 19 | ]); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /server.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 18 | 'next' => 'Next »', 19 | 20 | ); 21 | -------------------------------------------------------------------------------- /config.php_cs: -------------------------------------------------------------------------------- 1 | exclude(['views', 'config', 'database/migrations', 'lang', 'start']) 5 | ->in('app'); 6 | 7 | return Symfony\CS\Config\Config::create() 8 | ->fixers(['encoding', 'linefeed', 'indentation', 'tailing_spaces', 'unused_use', 'object_operator', 'phpdoc_params', 'visibility', 'short_tag', 'php_closing_tag', 'return', 'extra_empty_lines', 'lowercase_constants', 'lowercase_keywords', 'include', 'function_declaration', 'controls_spaces', 'spaces_cast', 'elseif', 'eof_ending', 'standardize_not_equal', 'new_with_braces']) 9 | ->finder($finder); 10 | -------------------------------------------------------------------------------- /app/config/testing/cache.php: -------------------------------------------------------------------------------- 1 | 'array', 19 | 20 | ); 21 | -------------------------------------------------------------------------------- /app/config/packages/artdarek/oauth-4-laravel/config.php: -------------------------------------------------------------------------------- 1 | 'Session', 15 | 16 | /** 17 | * Consumers 18 | */ 19 | 'consumers' => [ 20 | 'GitHub' => [ 21 | 'client_id' => getenv('GITHUB_CLIENT'), 22 | 'client_secret' => getenv('GITHUB_SECRET'), 23 | 'scope' => ['user:email'], 24 | ], 25 | ], 26 | 27 | ); 28 | -------------------------------------------------------------------------------- /app/database/seeds/CommentsTableSeeder.php: -------------------------------------------------------------------------------- 1 | $faker->paragraph(), 16 | 'snippet_id' => $faker->numberBetween(1, 100), 17 | 'user_id' => $faker->randomElement([1,2,3]), 18 | 'created_at' => $faker->dateTimeThisMonth(), 19 | 'updated_at' => $faker->dateTimeThisMonth() 20 | ]); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/views/partials/comment_form.blade.php: -------------------------------------------------------------------------------- 1 | {{ Form::open(['route' => 'comment.store', 'class' => 'comment-form clearfix']) }} 2 | {{ Form::hidden('snippet_id', $snippet->id) }} 3 |
4 | @if($errors->has()) 5 |

{{ $errors->first('body') }}

6 | @endif 7 | {{ Form::textarea('body', null, ['class' => 'form-control', 'rows' => '5', 'placeholder' => 'Your comment', 'tabindex' => '1', 'value' => Input::old('comment')]) }} 8 | @include('partials.markdown_help') 9 |
10 | 11 | {{ Form::close() }} 12 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./app/tests/ 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/config/testing/session.php: -------------------------------------------------------------------------------- 1 | 'array', 20 | 21 | ); 22 | -------------------------------------------------------------------------------- /app/database/migrations/2014_10_31_225054_create_tags_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $t->string('name'); 18 | $t->string('slug'); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | Schema::drop('tags'); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /app/views/snippets/create.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.main') 2 | 3 | @section('title', 'New Snippet') 4 | 5 | @section('content') 6 | 7 |
8 | 9 |
10 |
11 |

New Snippet

12 |
13 |
14 | 15 |
16 |
17 | @if($errors->has()) 18 |
    19 | @foreach($errors->all() as $message) 20 |
  • {{ $message }}
  • 21 | @endforeach 22 |
23 | @endif 24 | @include('partials.snippet_form') 25 |
26 |
27 | 28 |
29 | 30 | @stop 31 | -------------------------------------------------------------------------------- /app/views/snippets/edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.main') 2 | 3 | @section('title', 'Edit Snippet') 4 | 5 | @section('content') 6 | 7 |
8 | 9 |
10 |
11 |

Edit Snippet

12 |
13 |
14 | 15 |
16 |
17 | @if($errors->has()) 18 |
    19 | @foreach($errors->all() as $message) 20 |
  • {{ $message }}
  • 21 | @endforeach 22 |
23 | @endif 24 | @include('partials.snippet_form') 25 |
26 |
27 | 28 |
29 | 30 | @stop 31 | -------------------------------------------------------------------------------- /app/Vimrcfu/Providers/PersistenceServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->bind('Vimrcfu\Comments\CommentsRepository', 'Vimrcfu\Comments\EloquentCommentsRepository'); 10 | $this->app->bind('Vimrcfu\Snippets\SnippetsRepository', 'Vimrcfu\Snippets\EloquentSnippetsRepository'); 11 | $this->app->bind('Vimrcfu\Tags\TagsRepository', 'Vimrcfu\Tags\EloquentTagsRepository'); 12 | $this->app->bind('Vimrcfu\Users\UsersRepository', 'Vimrcfu\Users\EloquentUsersRepository'); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/Vimrcfu/Tags/TagsRepository.php: -------------------------------------------------------------------------------- 1 | 8 |
9 |

10 | Not found 11 |

12 |

The page you are looking for was not found. You can go to the home page, browse all snippets or try a search:

13 |
14 |
15 | @include('partials.search_form') 16 |
17 |
18 |
19 | 20 | 21 | 22 | @stop 23 | -------------------------------------------------------------------------------- /app/database/migrations/2014_11_01_134754_create_snippets_title_fulltext_index.php: -------------------------------------------------------------------------------- 1 | dropIndex('search_title'); 27 | }); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /app/database/migrations/2014_10_31_225259_create_taggables_table.php: -------------------------------------------------------------------------------- 1 | integer('tag_id'); 17 | $t->integer('taggable_id'); 18 | $t->string('taggable_type'); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | Schema::drop('taggables'); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /app/Vimrcfu/Exceptions/ValidationException.php: -------------------------------------------------------------------------------- 1 | errors = $errors; 19 | 20 | parent::__construct($message); 21 | } 22 | 23 | /** 24 | * @return Illuminate\Support\MessageBag 25 | */ 26 | public function getErrors() 27 | { 28 | return $this->errors; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /public/js/main.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | $('.votelink').on('click', function (e) { 3 | var link = $(this); 4 | e.preventDefault(); 5 | $.get(link.attr('href'), function (data) { 6 | toggle_link(link, data); 7 | }); 8 | }); 9 | $('.toggle-visibility').on('click', function () { 10 | toggle_visibility($(this)); 11 | }); 12 | }); 13 | 14 | function toggle_link(link, data) { 15 | link.removeClass('dark'); 16 | if(link.hasClass('up')) { 17 | $('.votelink.down').addClass('dark'); 18 | } else { 19 | $('.votelink.up').addClass('dark'); 20 | } 21 | $('.points').html(data); 22 | } 23 | 24 | function toggle_visibility(id) { 25 | elToHide = id.next(); 26 | elToHide.toggleClass('hidden'); 27 | } 28 | 29 | -------------------------------------------------------------------------------- /app/database/migrations/2014_10_25_122712_create_comments_table.php: -------------------------------------------------------------------------------- 1 | create(); 17 | 18 | $t->increments('id'); 19 | $t->text('body'); 20 | $t->integer('snippet_id'); 21 | $t->integer('user_id'); 22 | 23 | $t->timestamps(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::drop('comments'); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /app/views/partials/tracking.blade.php: -------------------------------------------------------------------------------- 1 | 16 | 17 | -------------------------------------------------------------------------------- /app/config/services.php: -------------------------------------------------------------------------------- 1 | array( 18 | 'domain' => '', 19 | 'secret' => '', 20 | ), 21 | 22 | 'mandrill' => array( 23 | 'secret' => '', 24 | ), 25 | 26 | 'stripe' => array( 27 | 'model' => 'User', 28 | 'secret' => '', 29 | ), 30 | 31 | ); 32 | -------------------------------------------------------------------------------- /app/database/migrations/2014_10_24_124915_create_snippets_table.php: -------------------------------------------------------------------------------- 1 | create(); 17 | 18 | $t->increments('id'); 19 | $t->string('title'); 20 | $t->text('body'); 21 | $t->text('description'); 22 | $t->integer('user_id'); 23 | 24 | $t->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::drop('snippets'); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /app/database/migrations/2014_10_28_035857_enable_snippets_fulltext_search.php: -------------------------------------------------------------------------------- 1 | dropIndex('search'); 28 | }); 29 | 30 | DB::statement('ALTER TABLE snippets ENGINE=InnoDB'); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /app/lang/en/reminders.php: -------------------------------------------------------------------------------- 1 | "Passwords must be at least six characters and match the confirmation.", 17 | 18 | "user" => "We can't find a user with that e-mail address.", 19 | 20 | "token" => "This password reset token is invalid.", 21 | 22 | "sent" => "Password reminder sent!", 23 | 24 | "reset" => "Password has been reset!", 25 | 26 | ); 27 | -------------------------------------------------------------------------------- /app/database/migrations/2014_10_26_042322_create_votes_table.php: -------------------------------------------------------------------------------- 1 | create(); 17 | 18 | $t->increments('id'); 19 | $t->integer('user_id')->unsigned(); 20 | $t->integer('snippet_id')->unsigned(); 21 | $t->tinyInteger('score'); 22 | $t->unique(['user_id', 'snippet_id']); 23 | 24 | $t->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::drop('votes'); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /app/database/migrations/2014_10_24_091019_create_users_table.php: -------------------------------------------------------------------------------- 1 | create(); 17 | 18 | $t->increments('id'); 19 | $t->string('github_id'); 20 | $t->string('github_url'); 21 | $t->string('avatar_url'); 22 | $t->string('email')->nullable(); 23 | $t->string('name'); 24 | 25 | $t->rememberToken(); 26 | $t->timestamps(); 27 | }); 28 | } 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::drop('users'); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/controllers/FeedController.php: -------------------------------------------------------------------------------- 1 | snippetsRepository = $snippetsRepository; 18 | } 19 | 20 | /** 21 | * Shows RSS feed for the last 20 Snippets. 22 | * 23 | * @return mixed 24 | */ 25 | public function index() 26 | { 27 | $snippets = $this->snippetsRepository->snippetsForFeed(); 28 | $content = View::make('pages.feed', compact('snippets')); 29 | 30 | return Response::make($content, '200') 31 | ->header('Content-Type', 'application/rss+xml'); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /app/views/partials/comment.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | {{ $comment->user->name }} 4 |
5 |
6 |

{{ $comment->user->name }} 7 | 8 | {{ $comment->created_at->diffForHumans() }} 9 | @if(Auth::check() && Auth::user()->id == $comment->user_id) 10 | [edit] 11 | @endif 12 | 13 | @if($comment->created_at != $comment->updated_at && $comment->created_at->diffInMinutes($comment->updated_at) > 5) 14 | 15 | @endif 16 |

17 | {{ Text::render($comment->body) }} 18 |
19 |
20 | -------------------------------------------------------------------------------- /app/views/pages/sitemap.blade.php: -------------------------------------------------------------------------------- 1 | ' ?> 2 | 3 | @foreach($snippets as $snippet) 4 | 5 | {{ URL::route('snippet.show', $snippet->id) }} 6 | {{ date('Y-m-d', strtotime($snippet->updated_at)) }} 7 | 8 | @endforeach 9 | 10 | @foreach($users as $user) 11 | 12 | {{ URL::route('user.show', $user->id) }} 13 | {{ date('Y-m-d', strtotime($user->updated_at)) }} 14 | 15 | @endforeach 16 | 17 | @foreach($tags as $tag) 18 | 19 | {{ URL::route('tag.show', $tag->slug) }} 20 | {{ date('Y-m-d', strtotime($tag->updated_at)) }} 21 | 22 | @endforeach 23 | 24 | @foreach($static as $page) 25 | 26 | {{URL::to($page)}} 27 | monthly 28 | 29 | @endforeach 30 | 31 | -------------------------------------------------------------------------------- /app/config/workbench.php: -------------------------------------------------------------------------------- 1 | '', 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Workbench Author E-Mail Address 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Like the option above, your e-mail address is used when generating new 24 | | workbench packages. The e-mail is placed in your composer.json file 25 | | automatically after the package is created by the workbench tool. 26 | | 27 | */ 28 | 29 | 'email' => '', 30 | 31 | ); 32 | -------------------------------------------------------------------------------- /app/database/seeds/UsersTableSeeder.php: -------------------------------------------------------------------------------- 1 | 800047, 11 | 'github_url' => 'https://github.com/florianbeer', 12 | 'avatar_url' => 'https://avatars1.githubusercontent.com/u/800047?v=2', 13 | 'email' => 'fb@42dev.eu', 14 | 'name' => 'Florian Beer' 15 | ]); 16 | 17 | User::create([ 18 | 'github_id' => 1, 19 | 'github_url' => 'https://github.com/octocat', 20 | 'avatar_url' => 'https://avatars1.githubusercontent.com/u/583231?v=2', 21 | 'email' => 'octocat@github.com', 22 | 'name' => 'monalisa octocat' 23 | ]); 24 | 25 | User::create([ 26 | 'github_id' => 75873, 27 | 'github_url' => 'https://github.com/sommero', 28 | 'avatar_url' => 'https://avatars1.githubusercontent.com/u/75873?v=2', 29 | 'email' => 'office@ojs.at', 30 | 'name' => 'Oliver J. Sommer' 31 | ]); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /public/js/tagging.js: -------------------------------------------------------------------------------- 1 | var tags = new Bloodhound({ 2 | datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'), 3 | queryTokenizer: Bloodhound.tokenizers.whitespace, 4 | dupDetector: function(remoteMatch, localMatch) { 5 | return remoteMatch.id === localMatch.id; 6 | }, 7 | prefetch: { 8 | url: '/tag/prefetch', 9 | ttl: 300000 10 | }, 11 | remote: { 12 | url: '/tag/search/%QUERY' 13 | } 14 | }); 15 | tags.initialize(); 16 | 17 | $('#tags').tagsinput({ 18 | tagClass: 'label label-default', 19 | trimValue: true, 20 | typeaheadjs: { 21 | name: 'tags', 22 | displayKey: 'name', 23 | valueKey: 'name', 24 | source: tags.ttAdapter() 25 | } 26 | }); 27 | 28 | $origEl = $('#tags'); 29 | $tagsEl = $('.bootstrap-tagsinput'); 30 | tagsinput = $origEl.tagsinput('input'); 31 | tagsinput.on('focus', function () { 32 | $tagsEl.addClass('focus'); 33 | }).on('blur', function () { 34 | $tagsEl.removeClass('focus'); 35 | $origEl.tagsinput('add', $('.tt-input').val()); 36 | tagsinput.val(''); 37 | }); 38 | -------------------------------------------------------------------------------- /app/config/view.php: -------------------------------------------------------------------------------- 1 | array(__DIR__.'/../views'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Pagination View 21 | |-------------------------------------------------------------------------- 22 | | 23 | | This view will be used to render the pagination link output, and can 24 | | be easily customized here to show any view you like. A clean view 25 | | compatible with Twitter's Bootstrap is given to you by default. 26 | | 27 | */ 28 | 29 | 'pagination' => 'pagination::simple', 30 | 31 | ); 32 | -------------------------------------------------------------------------------- /app/views/partials/statistics.blade.php: -------------------------------------------------------------------------------- 1 |

Statistics

2 | 29 | -------------------------------------------------------------------------------- /app/views/comments/edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.main') 2 | 3 | @section('title', 'Edit your comment') 4 | 5 | @section('content') 6 | 7 |
8 | 9 |
10 |
11 |

Edit comment

12 |
13 |
14 | 15 |
16 |
17 | {{ Form::model($comment, ['route' => ['comment.update', $comment->id], 'method' => 'PUT']) }} 18 | {{ Form::hidden('snippet_id', $comment->snippet->id) }} 19 |
20 | @if($errors->has()) 21 |

{{ $errors->first('body') }}

22 | @endif 23 | {{ Form::textarea('body', null, ['class' => 'form-control', 'rows' => '5', 'placeholder' => 'Your comment', 'tabindex' => '1', 'value' => Input::old('comment')]) }} 24 | @include('partials.markdown_help') 25 |
26 | 27 | {{ Form::close() }} 28 |
29 |
30 |
31 | 32 | @stop 33 | -------------------------------------------------------------------------------- /app/config/local/database.php: -------------------------------------------------------------------------------- 1 | array( 22 | 23 | 'mysql' => array( 24 | 'driver' => 'mysql', 25 | 'host' => getenv('DB_HOST'), 26 | 'database' => getenv('DB_NAME'), 27 | 'username' => getenv('DB_USER'), 28 | 'password' => getenv('DB_PASSWORD'), 29 | 'charset' => 'utf8', 30 | 'collation' => 'utf8_unicode_ci', 31 | 'prefix' => '', 32 | ), 33 | 34 | ), 35 | 36 | ); 37 | -------------------------------------------------------------------------------- /app/Vimrcfu/Snippets/SnippetsRepository.php: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 |
13 |

{{{ $title or 'New Snippets' }}}

14 |
15 | getTotal(); ?> 16 | {{ $snippetsTotal }} {{ Str::plural('Snippet', $snippetsTotal) }}
17 | Page {{ $snippets->getCurrentPage() }} of {{ $snippets->getLastPage() }} 18 |
19 |
20 | 21 |
22 | @include('partials.search_form') 23 |
24 |
25 | 26 |
27 |
28 | @include('partials.paginator') 29 |
30 |
31 | 32 |
33 |
34 | @foreach($snippets as $snippet) 35 | @include('partials.snippet', ['img' => true]) 36 | @endforeach 37 |
38 |
39 | 40 |
41 |
42 | @include('partials.paginator') 43 |
44 |
45 | 46 | 47 | 48 | @stop 49 | -------------------------------------------------------------------------------- /app/controllers/VotesController.php: -------------------------------------------------------------------------------- 1 | beforeFilter('auth', ['only' => ['up', 'down']]); 11 | } 12 | 13 | /** 14 | * Upvote Snippet and return score. 15 | * 16 | * @param string $snippet_id 17 | * @return mixed 18 | */ 19 | public function up($snippet_id) 20 | { 21 | $vote = Vote::firstOrNew([ 22 | 'user_id' => Auth::user()->id, 23 | 'snippet_id' => $snippet_id 24 | ]); 25 | $vote->score = 1; 26 | $vote->save(); 27 | 28 | $score = Snippet::find($snippet_id)->score; 29 | 30 | return Response::make($score, 200);; 31 | } 32 | 33 | /** 34 | * Downvote Snippet and return score. 35 | * 36 | * @param string $snippet_id 37 | * @return mixed 38 | */ 39 | public function down($snippet_id) 40 | { 41 | $vote = Vote::firstOrNew([ 42 | 'user_id' => Auth::user()->id, 43 | 'snippet_id' => $snippet_id 44 | ]); 45 | $vote->score = -1; 46 | $vote->save(); 47 | 48 | $score = Snippet::find($snippet_id)->score; 49 | 50 | return Response::make($score, 200);; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /app/Vimrcfu/Comments/EloquentCommentsRepository.php: -------------------------------------------------------------------------------- 1 | validator = $validator; 19 | } 20 | 21 | /** 22 | * @param array $input 23 | * @return mixed 24 | */ 25 | public function create($input) 26 | { 27 | $this->validator->validate($input); 28 | 29 | $comment = new Comment(); 30 | $comment->body = $input['body']; 31 | $comment->user_id = Auth::user()->id; 32 | $comment->snippet_id = $input['snippet_id']; 33 | $comment->save(); 34 | 35 | return $comment; 36 | } 37 | 38 | /** 39 | * @param Vimrcfu\Snippets\Comment $comment 40 | * @param array $input 41 | * @return mixed 42 | */ 43 | public function update(Comment $comment, $input) 44 | { 45 | $this->validator->validate($input); 46 | 47 | $comment->body = $input['body']; 48 | $comment->save(); 49 | 50 | return $comment; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /app/Vimrcfu/Validation/Validator.php: -------------------------------------------------------------------------------- 1 | validator = $validator; 24 | } 25 | 26 | /** 27 | * @param array $data 28 | * @throws Vimrcfu\Exceptions\ValidationException 29 | */ 30 | public function validate(array $data) 31 | { 32 | $this->validation = $this->validator->make($data, $this->getRules()); 33 | 34 | if ($this->validation->fails()) 35 | { 36 | throw new ValidationException('Validation failed', $this->getErrors()); 37 | } 38 | 39 | return true; 40 | } 41 | 42 | /** 43 | * @return array 44 | */ 45 | protected function getRules() 46 | { 47 | return $this->rules; 48 | } 49 | 50 | /** 51 | * @return mixed 52 | */ 53 | protected function getErrors() 54 | { 55 | return $this->validation->errors(); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /app/Vimrcfu/Snippets/Snippet.php: -------------------------------------------------------------------------------- 1 | belongsTo('Vimrcfu\Users\User'); 12 | } 13 | 14 | public function comments() 15 | { 16 | return $this->hasMany('Vimrcfu\Comments\Comment'); 17 | } 18 | 19 | public function votes() 20 | { 21 | return $this->hasMany('Vimrcfu\Votes\Vote'); 22 | } 23 | 24 | public function tags() 25 | { 26 | return $this->morphToMany('Vimrcfu\Tags\Tag', 'taggable'); 27 | } 28 | 29 | public function getScoreAttribute() 30 | { 31 | return $this->votes()->sum('score'); 32 | } 33 | 34 | public function hasUserVoted($user_id) 35 | { 36 | $vote = $this->votes()->where('user_id', '=', $user_id)->first(); 37 | if ( $vote ) 38 | { 39 | return (int) $vote->score; 40 | } 41 | } 42 | 43 | public function hasTag($tag) 44 | { 45 | return $this->tags->contains($tag->id); 46 | } 47 | 48 | public function tagnames() 49 | { 50 | $tagnames = []; 51 | $tags = $this->tags()->get(array('name')); 52 | 53 | foreach ($tags as $tag) { 54 | $tagnames[] = $tag->name; 55 | } 56 | 57 | return $tagnames; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /app/Vimrcfu/Users/User.php: -------------------------------------------------------------------------------- 1 | hasMany('Vimrcfu\Snippets\Snippet')->orderBy('id', 'DESC'); 21 | } 22 | 23 | public function comments() 24 | { 25 | return $this->hasMany('Vimrcfu\Comments\Comment')->orderBy('id', 'DESC'); 26 | } 27 | 28 | public function votes() 29 | { 30 | return $this->hasMany('Vimrcfu\Votes\Vote')->where('score', '=', 1)->orderBy('id', 'DESC'); 31 | } 32 | 33 | public function tags() 34 | { 35 | $tag_ids = []; 36 | $snippets = $this->snippets()->with('tags')->get(); 37 | foreach($snippets as $snippet) 38 | { 39 | foreach($snippet->tags as $tag) 40 | { 41 | $tag_ids[] = $tag->id; 42 | } 43 | } 44 | $tag_ids = array_unique($tag_ids); 45 | 46 | return Tag::find($tag_ids); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/views/partials/snippet.blade.php: -------------------------------------------------------------------------------- 1 |
2 | @if($img == true) 3 |
4 | 5 | {{ $snippet->user->name }} 6 | 7 |
8 |
9 | @else 10 |
11 | @endif 12 |

{{{ $snippet->title }}}

13 |
14 |

15 | {{ $snippet->created_at->diffForHumans() }} 16 | @if (Auth::check() && $snippet->user_id === Auth::user()->id) 17 | [edit] 18 | @endif 19 |
20 | by {{ $snippet->user->name }} 21 |

22 |

23 | score; ?> 24 | {{ $score }} {{ Str::plural('Point', $score) }}
25 | {{ count($snippet->comments) }} {{ Str::plural('Comment', count($snippet->comments)) }} 26 |

27 |
28 |
29 |
30 | -------------------------------------------------------------------------------- /app/views/search/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.main') 2 | 3 | @section('title', 'Search Results') 4 | 5 | @section('content') 6 | 7 |
8 | 9 |
10 |
11 |

Search for {{ Input::get('q') }}

12 |
13 | {{ $total }} {{ Str::plural('Result', $total) }}
14 | @if($snippets->getLastPage() > 1) 15 | Page {{ $snippets->getCurrentPage() }} of {{ $snippets->getLastPage() }} 16 | @endif 17 |
18 |
19 | 20 |
21 | @include('partials.search_form') 22 |
23 |
24 | 25 |
26 |
27 | @include('partials.paginator') 28 |
29 |
30 | 31 |
32 |
33 | @foreach($snippets as $snippet) 34 | @include('partials.snippet', ['img' => true]) 35 | @endforeach 36 |
37 | 38 |
39 | @include('partials.tagcloud', ['title' => 'Related ' . Str::plural('Tag', count($tags))]) 40 |
41 |
42 | 43 |
44 |
45 | @include('partials.paginator') 46 |
47 |
48 | 49 |
50 | 51 | @stop 52 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "florianbeer/vimrcfu", 3 | "description": "Source code for the vimrcfu.com website", 4 | "keywords": ["website", "vim", "vimrc"], 5 | "homepage": "http://vimrcfu.com", 6 | "license": "CC-BY-NC-SA-4.0", 7 | "type": "project", 8 | "authors": [ 9 | { 10 | "name": "Florian Beer", 11 | "email": "fb@42dev.eu", 12 | "homepage": "http://blog.no-panic.at", 13 | "role": "Developer" 14 | } 15 | ], 16 | "require": { 17 | "laravel/framework": "4.2.*", 18 | "artdarek/oauth-4-laravel": "1.0.5", 19 | "michelf/php-markdown": "1.4.*" 20 | }, 21 | "require-dev": { 22 | "fzaninotto/faker": "~1.4" 23 | }, 24 | "autoload": { 25 | "classmap": [ 26 | "app/commands", 27 | "app/controllers", 28 | "app/database/migrations", 29 | "app/database/seeds", 30 | "app/tests/TestCase.php" 31 | ], 32 | "psr-4": { 33 | "Vimrcfu\\": "app/Vimrcfu" 34 | } 35 | }, 36 | "scripts": { 37 | "post-install-cmd": [ 38 | "php artisan clear-compiled", 39 | "php artisan optimize" 40 | ], 41 | "post-update-cmd": [ 42 | "php artisan clear-compiled", 43 | "php artisan optimize" 44 | ], 45 | "post-create-project-cmd": [ 46 | "php artisan key:generate" 47 | ] 48 | }, 49 | "config": { 50 | "preferred-install": "dist" 51 | }, 52 | "minimum-stability": "stable" 53 | } 54 | -------------------------------------------------------------------------------- /app/controllers/TagsController.php: -------------------------------------------------------------------------------- 1 | repository = $repository; 19 | } 20 | 21 | /** 22 | * Incremental search for Tags, 23 | * Used in autocomplete input field. 24 | * 25 | * @return mixed 26 | */ 27 | public function search($string) 28 | { 29 | return $this->repository->searchByName($string); 30 | } 31 | 32 | /** 33 | * Returns top Tags array, 34 | * Used in prefetch for autocomplete. 35 | * 36 | * @return array 37 | */ 38 | public function prefetch() 39 | { 40 | return $this->repository->topTags(); 41 | } 42 | 43 | /** 44 | * Displays all Snippets for a specific Tag. 45 | * 46 | * @param string $slug 47 | * @return mixed 48 | */ 49 | public function show($slug) 50 | { 51 | $tag = Tag::where('slug', $slug)->first(); 52 | 53 | if ( ! $tag) 54 | { 55 | App::abort(404); 56 | } 57 | 58 | $snippets = $tag->snippets()->paginate(10); 59 | 60 | return View::make('snippets.index', compact('snippets')) 61 | ->with('title', $tag->name); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /app/controllers/SearchController.php: -------------------------------------------------------------------------------- 1 | snippetsRepository = $snippetsRepository; 25 | $this->tagsRepository = $tagsRepository; 26 | } 27 | 28 | /** 29 | * Shows the search page or redirects to Snippets 30 | * index page in case no searchterm was entered. 31 | * 32 | * @return mixed 33 | */ 34 | public function index() 35 | { 36 | $search = Input::get('q'); 37 | if ( ! empty($search)) 38 | { 39 | $searchresult = $this->snippetsRepository->fulltextSearch($search); 40 | $tags = $this->tagsRepository->relatedTags($search); 41 | 42 | return View::make('search.index') 43 | ->withSnippets($searchresult['items']) 44 | ->withTotal($searchresult['total']) 45 | ->withTags($tags); 46 | } 47 | 48 | return Redirect::route('snippet.index'); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /app/views/partials/snippet_form.blade.php: -------------------------------------------------------------------------------- 1 | @if(empty($snippet->title)) 2 | {{ Form::model($snippet, ['route' => 'snippet.store']) }} 3 | @else 4 | {{ Form::model($snippet, ['route' => ['snippet.update', $snippet->id], 'method' => 'PUT']) }} 5 | @endif 6 |
7 | 8 | {{ Form::text('title', null, ['class' => 'form-control', 'id' => 'title', 'placeholder' => 'Enter a descriptive title', 'autofocus']) }} 9 |
10 |
11 | 12 | {{ Form::textarea('description', null, ['class' => 'form-control', 'id' => 'description', 'placeholder' => 'Describe exactly what your snippet achieves or which behaviour it adds.', 'rows' => '3']) }} 13 | @include('partials.markdown_help') 14 |
15 |
16 | 17 | {{ Form::text('tags', implode(',', $snippet->tagnames()), ['class' => 'form-control', 'id' => 'tags', 'placeholder' => 'Choose tags', 'data-role' => 'tagsinput']) }} 18 |
19 |
20 | 21 | {{ Form::textarea('body', null, ['class' => 'form-control snippet', 'id' => 'body', 'placeholder' => 'Paste your snippet here.', 'rows' => '6']) }} 22 |
23 | 24 | {{ Form::close() }} 25 | 26 | @section('script') 27 | {{ HTML::script('js/vendor/bootstrap-tagsinput.min.js') }} 28 | {{ HTML::script('js/vendor/typeahead.bundle.min.js') }} 29 | {{ HTML::script('js/tagging.js') }} 30 | @stop 31 | -------------------------------------------------------------------------------- /app/views/partials/navbar.blade.php: -------------------------------------------------------------------------------- 1 | 32 | -------------------------------------------------------------------------------- /app/routes.php: -------------------------------------------------------------------------------- 1 | 'home', 'uses' => 'PagesController@home']); 3 | Route::get('faq', ['as' => 'faq', 'uses' => 'PagesController@faq']); 4 | Route::get('sitemap.xml', 'PagesController@sitemap'); 5 | 6 | Route::get('feed', 'FeedController@index'); 7 | 8 | Route::get('search', ['as' => 'search', 'uses' => 'SearchController@index']); 9 | 10 | Route::model('snippet', 'Vimrcfu\Snippets\Snippet'); 11 | Route::get('snippet/hot', ['as' => 'snippet.hot', 'uses' => 'SnippetsController@hot']); 12 | Route::resource('snippet', 'SnippetsController', ['except' => 'destroy']); 13 | Route::get('snippet/{id}/up', ['as' => 'vote.up', 'uses' => 'VotesController@up']); 14 | Route::get('snippet/{id}/down', ['as' => 'vote.down', 'uses' => 'VotesController@down']); 15 | 16 | Route::model('user', 'Vimrcfu\Users\User'); 17 | Route::get('login', ['as' => 'login', 'uses' => 'UsersController@login']); 18 | Route::get('logout', ['as' => 'logout', 'uses' => 'UsersController@logout']); 19 | Route::resource('user', 'UsersController', ['only' => 'show']); 20 | Route::get('user/{user}/upvotes', ['as' => 'user.votes', 'uses' => 'UsersController@upvotes']); 21 | 22 | Route::model('comment', 'Vimrcfu\Comments\Comment'); 23 | Route::resource('comment', 'CommentsController', ['only' => ['store', 'edit', 'update']]); 24 | 25 | Route::get('tag/search/{name}', ['uses' => 'TagsController@search']); 26 | Route::get('tag/prefetch', ['uses' => 'TagsController@prefetch']); 27 | Route::get('tag/{slug}', ['as' => 'tag.show', 'uses' => 'TagsController@show']); 28 | 29 | Route::get('snake', function () { 30 | return Response::view('errors.503', ['title' => 'Snake'], 503); 31 | }); 32 | -------------------------------------------------------------------------------- /app/controllers/CommentsController.php: -------------------------------------------------------------------------------- 1 | beforeFilter('auth', ['only' => ['store', 'edit', 'update']]); 19 | $this->repository = $repository; 20 | } 21 | 22 | /** 23 | * Stores new Comment in storage. 24 | * 25 | * @return mixed 26 | */ 27 | public function store() 28 | { 29 | $comment = $this->repository->create(Input::all()); 30 | 31 | return Redirect::route('snippet.show', $comment->snippet->id); 32 | } 33 | 34 | /** 35 | * Shows the form for editing a Comment. 36 | * 37 | * @param Vimrcfu\Comments\Comment $comment 38 | * @return mixed 39 | */ 40 | public function edit(Comment $comment) 41 | { 42 | if ( Auth::user()->id != $comment->user_id ) 43 | { 44 | return Redirect::home(); 45 | } 46 | 47 | return View::make('comments.edit', compact('comment')); 48 | } 49 | 50 | /** 51 | * Update a Comment in storage. 52 | * 53 | * @param Vimrcfu\Comments\Comment $comment 54 | * @return mixed 55 | */ 56 | public function update(Comment $comment) 57 | { 58 | if ( Auth::user()->id != $comment->user_id ) 59 | { 60 | return Redirect::home(); 61 | } 62 | 63 | $comment = $this->repository->update($comment, Input::all()); 64 | 65 | return Redirect::route('snippet.show', $comment->snippet->id); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | /* 10 | |-------------------------------------------------------------------------- 11 | | Register The Auto Loader 12 | |-------------------------------------------------------------------------- 13 | | 14 | | Composer provides a convenient, automatically generated class loader 15 | | for our application. We just need to utilize it! We'll require it 16 | | into the script here so that we do not have to worry about the 17 | | loading of any our classes "manually". Feels great to relax. 18 | | 19 | */ 20 | 21 | require __DIR__.'/../bootstrap/autoload.php'; 22 | 23 | /* 24 | |-------------------------------------------------------------------------- 25 | | Turn On The Lights 26 | |-------------------------------------------------------------------------- 27 | | 28 | | We need to illuminate PHP development, so let's turn on the lights. 29 | | This bootstraps the framework and gets it ready for use, then it 30 | | will load up this application so that we can run it and send 31 | | the responses back to the browser and delight these users. 32 | | 33 | */ 34 | 35 | $app = require_once __DIR__.'/../bootstrap/start.php'; 36 | 37 | /* 38 | |-------------------------------------------------------------------------- 39 | | Run The Application 40 | |-------------------------------------------------------------------------- 41 | | 42 | | Once we have the application, we can simply call the run method, 43 | | which will execute the request and send the response back to 44 | | the client's browser allowing them to enjoy the creative 45 | | and wonderful application we have whipped up for them. 46 | | 47 | */ 48 | 49 | $app->run(); 50 | -------------------------------------------------------------------------------- /app/config/remote.php: -------------------------------------------------------------------------------- 1 | 'production', 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Remote Server Connections 21 | |-------------------------------------------------------------------------- 22 | | 23 | | These are the servers that will be accessible via the SSH task runner 24 | | facilities of Laravel. This feature radically simplifies executing 25 | | tasks on your servers, such as deploying out these applications. 26 | | 27 | */ 28 | 29 | 'connections' => array( 30 | 31 | 'production' => array( 32 | 'host' => '', 33 | 'username' => '', 34 | 'password' => '', 35 | 'key' => '', 36 | 'keyphrase' => '', 37 | 'root' => '/var/www', 38 | ), 39 | 40 | ), 41 | 42 | /* 43 | |-------------------------------------------------------------------------- 44 | | Remote Server Groups 45 | |-------------------------------------------------------------------------- 46 | | 47 | | Here you may list connections under a single group name, which allows 48 | | you to easily access all of the servers at once using a short name 49 | | that is extremely easy to remember, such as "web" or "database". 50 | | 51 | */ 52 | 53 | 'groups' => array( 54 | 55 | 'web' => array('production') 56 | 57 | ), 58 | 59 | ); 60 | -------------------------------------------------------------------------------- /app/views/pages/feed.blade.php: -------------------------------------------------------------------------------- 1 | 3 | 11 | '; ?> 12 | 13 | 14 | vimrcfu - Share your best vimrc snippets. 15 | 16 | {{ Config::get('app.url') }} 17 | Gather your vimrc snippets on this site and let others learn from your fu. 18 | {{ \Carbon\Carbon::createFromTimeStamp(time())->toRssString() }} 19 | en-US 20 | hourly 21 | 1 22 | http://vimrcfu.com 23 | @foreach($snippets as $snippet) 24 | 25 | {{ Text::xmlentities($snippet->title) }} 26 | {{ Config::get('app.url') }}/snippet/{{ $snippet->id }} 27 | {{ $snippet->created_at->toRssString() }} 28 | user->name }}]]> 29 | http://vimrcfu.com/snippet/{{ $snippet->id }} 30 | description) }}]]> 31 | {{ Text::renderForRss($snippet->description) }}

{{ htmlentities($snippet->body) }}

]]>
32 |
33 | @endforeach 34 |
35 |
36 | -------------------------------------------------------------------------------- /app/views/pages/home.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.main') 2 | 3 | @section('title', 'Share your best vimrc snippets') 4 | 5 | @section('content') 6 | 7 |
8 |
9 |

Share your knowledge

10 |

Gather your vimrc snippets on this site and let others learn from your fu.

11 |

Post a new snippet »

12 |
13 |
14 | 15 |
16 | 17 |
18 |
19 |

New Snippets

20 | @foreach($snippets as $snippet) 21 | @include('partials.snippet', ['img' => true]) 22 | @endforeach 23 |
24 | 27 |
28 |
29 | 30 |
31 |
32 |
33 | @include('partials.search_form') 34 |
35 |
36 | 37 |
38 |
39 | @include('partials.statistics') 40 |
41 |
42 | 43 |
44 |
45 | @include('partials.tagcloud') 46 |
47 |
48 | 49 |
50 |
51 | {{ Text::renderInclude('news') }} 52 |
53 |
54 |
55 | 56 |
57 | 58 |
59 | 60 | @stop 61 | -------------------------------------------------------------------------------- /bootstrap/paths.php: -------------------------------------------------------------------------------- 1 | __DIR__.'/../app', 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Public Path 21 | |-------------------------------------------------------------------------- 22 | | 23 | | The public path contains the assets for your web application, such as 24 | | your JavaScript and CSS files, and also contains the primary entry 25 | | point for web requests into these applications from the outside. 26 | | 27 | */ 28 | 29 | 'public' => __DIR__.'/../public', 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Base Path 34 | |-------------------------------------------------------------------------- 35 | | 36 | | The base path is the root of the Laravel installation. Most likely you 37 | | will not need to change this value. But, if for some wild reason it 38 | | is necessary you will do so here, just proceed with some caution. 39 | | 40 | */ 41 | 42 | 'base' => __DIR__.'/..', 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Storage Path 47 | |-------------------------------------------------------------------------- 48 | | 49 | | The storage path is used by Laravel to store cached Blade views, logs 50 | | and other pieces of information. You may modify the path here when 51 | | you want to change the location of this directory for your apps. 52 | | 53 | */ 54 | 55 | 'storage' => __DIR__.'/../app/storage', 56 | 57 | ); 58 | -------------------------------------------------------------------------------- /app/views/users/show.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.main') 2 | 3 | @section('title', $user->name) 4 | 5 | @section('content') 6 | 7 |
8 | 9 |
10 |
11 |

{{ $user->name }}

12 |
13 |
14 | 15 |
16 |
17 | {{ $user->name }} 18 |

19 | {{ $total }} 20 | {{ Str::plural('Snippet', $total) }} 21 |

22 |

23 | {{ $user->votes->count() - $total}} 24 | Up{{ Str::plural('vote', $user->votes->count()) }} 25 |

26 |

27 | {{ $user->comments->count() }} 28 | {{ Str::plural('Comment', $user->comments->count()) }} 29 |

30 |

31 | {{ $tags->count() }} 32 | {{ Str::plural('Tag', $tags->count()) }} 33 |

34 |

GitHub Page »

35 |
@include('partials.tagcloud', ['title' => ''])
36 |
37 | 38 |
39 |
40 |
41 | @include('partials.paginator') 42 |
43 |
44 | @foreach($snippets as $snippet) 45 | @if(Request::is('user/*/upvotes')) 46 | @include('partials.snippet', ['img' => true]) 47 | @else 48 | @include('partials.snippet', ['img' => false]) 49 | @endif 50 | @endforeach 51 |
52 |
53 | @include('partials.paginator') 54 |
55 |
56 |
57 |
58 | 59 |
60 | 61 | @stop 62 | -------------------------------------------------------------------------------- /public/js/vendor/bootstrap-tagsinput.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"dist/bootstrap-tagsinput-angular.min.js","sources":["src/bootstrap-tagsinput-angular.js"],"names":["angular","module","directive","getItemProperty","scope","property","isFunction","$parent","item","undefined","restrict","model","template","replace","link","element","attrs","$","isArray","select","typeaheadSourceArray","typeaheadSource","split","length","tagsinput","options","typeahead","source","itemValue","itemvalue","itemText","itemtext","confirmKeys","confirmkeys","JSON","parse","tagClass","tagclass","i","on","event","indexOf","push","idx","splice","prev","slice","$watch","added","filter","removed"],"mappings":";;;;;AAAAA,QAAQC,OAAO,0BACdC,UAAU,sBAAuB,WAEhC,QAASC,GAAgBC,EAAOC,GAC9B,MAAKA,GAGDL,QAAQM,WAAWF,EAAMG,QAAQF,IAC5BD,EAAMG,QAAQF,GAEhB,SAASG,GACd,MAAOA,GAAKH,IANLI,OAUX,OACEC,SAAU,KACVN,OACEO,MAAO,YAETC,SAAU,6BACVC,SAAS,EACTC,KAAM,SAASV,EAAOW,EAASC,GAC7BC,EAAE,WACKjB,QAAQkB,QAAQd,EAAMO,SACzBP,EAAMO,SAER,IAAIQ,GAASF,EAAE,SAAUF,GACrBK,EAAuBJ,EAAMK,gBAAkBL,EAAMK,gBAAgBC,MAAM,KAAO,KAClFD,EAAkBD,EACjBA,EAAqBG,OAAS,EAC3BnB,EAAMG,QAAQa,EAAqB,IAAIA,EAAqB,IAC1DhB,EAAMG,QAAQa,EAAqB,IACvC,IAEND,GAAOK,UAAUpB,EAAMG,QAAQS,EAAMS,SAAW,MAC9CC,WACEC,OAAW3B,QAAQM,WAAWe,GAAmBA,EAAkB,MAErEO,UAAWzB,EAAgBC,EAAOY,EAAMa,WACxCC,SAAW3B,EAAgBC,EAAOY,EAAMe,UACxCC,YAAc7B,EAAgBC,EAAOY,EAAMiB,aAAeC,KAAKC,MAAMnB,EAAMiB,cAAgB,IAC3FG,SAAWpC,QAAQM,WAAWF,EAAMG,QAAQS,EAAMqB,WAAajC,EAAMG,QAAQS,EAAMqB,UAAY,WAAiB,MAAOrB,GAAMqB,WAG/H,KAAK,GAAIC,GAAI,EAAGA,EAAIlC,EAAMO,MAAMY,OAAQe,IACtCnB,EAAOK,UAAU,MAAOpB,EAAMO,MAAM2B,GAGtCnB,GAAOoB,GAAG,YAAa,SAASC,GACU,KAApCpC,EAAMO,MAAM8B,QAAQD,EAAMhC,OAC5BJ,EAAMO,MAAM+B,KAAKF,EAAMhC,QAG3BW,EAAOoB,GAAG,cAAe,SAASC,GAChC,GAAIG,GAAMvC,EAAMO,MAAM8B,QAAQD,EAAMhC,KACxB,MAARmC,GACFvC,EAAMO,MAAMiC,OAAOD,EAAK,IAK5B,IAAIE,GAAOzC,EAAMO,MAAMmC,OACvB1C,GAAM2C,OAAO,QAAS,WACpB,GAEIT,GAFAU,EAAQ5C,EAAMO,MAAMsC,OAAO,SAASX,GAAI,MAA2B,KAApBO,EAAKJ,QAAQH,KAC5DY,EAAUL,EAAKI,OAAO,SAASX,GAAI,MAAkC,KAA3BlC,EAAMO,MAAM8B,QAAQH,IAMlE,KAHAO,EAAOzC,EAAMO,MAAMmC,QAGdR,EAAI,EAAGA,EAAIY,EAAQ3B,OAAQe,IAC9BnB,EAAOK,UAAU,SAAU0B,EAAQZ,GAOrC,KAHAnB,EAAOK,UAAU,WAGZc,EAAI,EAAGA,EAAIU,EAAMzB,OAAQe,IAC5BnB,EAAOK,UAAU,MAAOwB,EAAMV,MAE/B"} -------------------------------------------------------------------------------- /public/js/vendor/html5shiv.js: -------------------------------------------------------------------------------- 1 | (function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); 2 | a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x"; 3 | c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| 4 | "undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment(); 5 | for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;drepository = $repository; 29 | $this->tagsRepository = $tagsRepository; 30 | } 31 | 32 | /** 33 | * Displays the home page. 34 | * 35 | * @return Response 36 | */ 37 | public function home() 38 | { 39 | $newSnippets = $this->repository->newSnippets(); 40 | $topSnippet = $this->repository->topSnippet(); 41 | $topCommented = $this->repository->topCommented(); 42 | $topTags = $this->tagsRepository->topTags(); 43 | $title = 'Popular Tags'; 44 | 45 | return View::make('pages.home') 46 | ->withSnippets($newSnippets) 47 | ->withSnippetsCount(Snippet::remember(5)->get()->count()) 48 | ->withCommentsCount(Comment::remember(5)->get()->count()) 49 | ->withUsersCount(User::remember(5)->get()->count()) 50 | ->withTopSnippet($topSnippet) 51 | ->withTopComments($topCommented) 52 | ->withTags($topTags) 53 | ->withTitle($title); 54 | 55 | } 56 | 57 | /** 58 | * Displays Frequently Asked Questions. 59 | * 60 | * @return void 61 | */ 62 | public function faq() 63 | { 64 | return View::make('pages.markdown') 65 | ->withTitle('Frequently Asked Questions') 66 | ->withFile('faq'); 67 | } 68 | 69 | /** 70 | * Displays the XML sitemap. 71 | * 72 | * @return void 73 | */ 74 | public function sitemap() 75 | { 76 | $static = [ 77 | 'faq', 78 | 'search', 79 | 'snippet' 80 | ]; 81 | 82 | return View::make('pages.sitemap') 83 | ->with('static', $static) 84 | ->with('snippets', Snippet::all()) 85 | ->with('tags', Tag::all()) 86 | ->with('users', User::all()); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /app/config/auth.php: -------------------------------------------------------------------------------- 1 | 'eloquent', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Authentication Model 23 | |-------------------------------------------------------------------------- 24 | | 25 | | When using the "Eloquent" authentication driver, we need to know which 26 | | Eloquent model should be used to retrieve your users. Of course, it 27 | | is often just the "User" model but you may use whatever you like. 28 | | 29 | */ 30 | 31 | 'model' => 'Vimrcfu\Users\User', 32 | 33 | /* 34 | |-------------------------------------------------------------------------- 35 | | Authentication Table 36 | |-------------------------------------------------------------------------- 37 | | 38 | | When using the "Database" authentication driver, we need to know which 39 | | table should be used to retrieve your users. We have chosen a basic 40 | | default value but you may easily change it to any table you like. 41 | | 42 | */ 43 | 44 | 'table' => 'users', 45 | 46 | /* 47 | |-------------------------------------------------------------------------- 48 | | Password Reminder Settings 49 | |-------------------------------------------------------------------------- 50 | | 51 | | Here you may set the settings for password reminders, including a view 52 | | that should be used as your password reminder e-mail. You will also 53 | | be able to set the name of the table that holds the reset tokens. 54 | | 55 | | The "expire" time is the number of minutes that the reminder should be 56 | | considered valid. This security feature keeps tokens short-lived so 57 | | they have less time to be guessed. You may change this as needed. 58 | | 59 | */ 60 | 61 | 'reminder' => array( 62 | 63 | 'email' => 'emails.auth.reminder', 64 | 65 | 'table' => 'password_reminders', 66 | 67 | 'expire' => 60, 68 | 69 | ), 70 | 71 | ); 72 | -------------------------------------------------------------------------------- /app/Vimrcfu/Tags/EloquentTagsRepository.php: -------------------------------------------------------------------------------- 1 | get(); 16 | } 17 | 18 | public function getByName($name) 19 | { 20 | return Tag::whereName($name)->first(); 21 | } 22 | 23 | /** 24 | * @var Vimrcfu\Snippets\Snippet $snippet 25 | * @var Vimrcfu\Tags\Tag $tags 26 | */ 27 | public function updateTags($snippet, $tagNamesString) 28 | { 29 | $tagNamesArray = explode(',', $tagNamesString); 30 | $snippetTagNamesArray = $snippet->tagnames(); 31 | 32 | $tagNamesToRemove = array_diff($snippetTagNamesArray, $tagNamesArray); 33 | $tagNamesToAdd = array_diff($tagNamesArray, $snippetTagNamesArray); 34 | 35 | foreach($tagNamesToRemove as $tagname) 36 | { 37 | $tag = $this->getByName($tagname); 38 | $snippet->tags()->detach($tag); 39 | } 40 | 41 | foreach($tagNamesToAdd as $tagname) 42 | { 43 | $tagname = trim($tagname); 44 | if ($tagname) { 45 | $tag = Tag::firstOrCreate(['name' => $tagname, 'slug' => Str::slug($tagname)]); 46 | $snippet->tags()->attach($tag->id); 47 | } 48 | } 49 | } 50 | 51 | /** 52 | * @return array 53 | */ 54 | public static function topTags() 55 | { 56 | $topTags = Cache::remember('topTags', 5, function () 57 | { 58 | $topTagsResult = DB::select(DB::raw(' 59 | SELECT tags.name, tag_id, count(tag_id) count, tags.slug FROM taggables 60 | JOIN tags ON taggables.tag_id = tags.id 61 | GROUP BY tag_id ORDER BY count DESC LIMIT 14' 62 | )); 63 | 64 | return (isset($topTagsResult)) ? $topTagsResult : []; 65 | }); 66 | 67 | $topTags = array_map(function ($tags) { 68 | return (object) [ 69 | 'id' => $tags->tag_id, 70 | 'name' => $tags->name, 71 | 'slug' => $tags->slug 72 | ]; 73 | }, $topTags); 74 | 75 | return $topTags; 76 | } 77 | 78 | /** 79 | * @param string search 80 | * @param int $count 81 | * @return mixed 82 | */ 83 | public function relatedTags($search, $count = 20) 84 | { 85 | return Tag::where('name', 'LIKE', '%' . $search . '%')->take($count)->get(); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/config/queue.php: -------------------------------------------------------------------------------- 1 | 'sync', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Queue Connections 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may configure the connection information for each server that 26 | | is used by your application. A default configuration has been added 27 | | for each back-end shipped with Laravel. You are free to add more. 28 | | 29 | */ 30 | 31 | 'connections' => array( 32 | 33 | 'sync' => array( 34 | 'driver' => 'sync', 35 | ), 36 | 37 | 'beanstalkd' => array( 38 | 'driver' => 'beanstalkd', 39 | 'host' => 'localhost', 40 | 'queue' => 'default', 41 | 'ttr' => 60, 42 | ), 43 | 44 | 'sqs' => array( 45 | 'driver' => 'sqs', 46 | 'key' => 'your-public-key', 47 | 'secret' => 'your-secret-key', 48 | 'queue' => 'your-queue-url', 49 | 'region' => 'us-east-1', 50 | ), 51 | 52 | 'iron' => array( 53 | 'driver' => 'iron', 54 | 'host' => 'mq-aws-us-east-1.iron.io', 55 | 'token' => 'your-token', 56 | 'project' => 'your-project-id', 57 | 'queue' => 'your-queue-name', 58 | 'encrypt' => true, 59 | ), 60 | 61 | 'redis' => array( 62 | 'driver' => 'redis', 63 | 'queue' => 'default', 64 | ), 65 | 66 | ), 67 | 68 | /* 69 | |-------------------------------------------------------------------------- 70 | | Failed Queue Jobs 71 | |-------------------------------------------------------------------------- 72 | | 73 | | These options configure the behavior of failed queue job logging so you 74 | | can control which database and table are used to store the jobs that 75 | | have failed. You may change them to any database / table you wish. 76 | | 77 | */ 78 | 79 | 'failed' => array( 80 | 81 | 'database' => 'mysql', 'table' => 'failed_jobs', 82 | 83 | ), 84 | 85 | ); 86 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guide 2 | 3 | This page contains guidelines for contributing to **vimrcfu**. Please review these guidelines before submitting any pull requests to the project. 4 | 5 | This contributing guide is based on the original [Laravel Contribution Guide](https://github.com/laravel/framework/blob/4.1/CONTRIBUTING.md). 6 | 7 | ## Which Branch? 8 | 9 | All changes targeting the current version should be sent to the `dev` branch. 10 | 11 | ## Pull Requests 12 | 13 | Before sending a pull request for a new feature, you should first create an issue with `[Proposal]` in the title. The proposal should describe the new feature, as well as implementation ideas. The proposal will then be reviewed and either approved or denied. Once a proposal is approved, a pull request may be created implementing the new feature. 14 | 15 | Pull requests for bugs may be sent without creating any proposal issue. If you believe that you know of a solution for a bug that has been filed on GitHub, please leave a comment detailing your proposed fix. 16 | 17 | ### Feature Requests 18 | 19 | If you have an idea for a new feature you would like to see added to **vimrcfu**, you may create an issue on GitHub with `[Request]` in the title. The feature request will then be reviewed. 20 | 21 | ## Coding Standards 22 | 23 | Adherence to coding standard can be enforced with [PHP Coding Standards Fixer](http://cs.sensiolabs.org). 24 | 25 | Install with `composer global require fabpot/php-cs-fixer @stable` and then in the direcotry where you checked out the repository execute: `php-cs-fixer fix --config-file="config.php_cs"` 26 | 27 | The following should be adhered to throughout the code base ([Laravel 4.2 Coding Style](http://laravel.com/docs/4.2/contributions#coding-style)): 28 | * Namespace declarations should be on the same line as `title) 4 | 5 | @section('content') 6 | 7 |
8 | 9 |
10 |
11 |

{{{ $snippet->title }}}

12 |
13 | 14 |
15 |
16 | score; ?> 17 | {{ $score }} {{ Str::plural('Point', $score) }} 18 | @if(Auth::check()) 19 | hasUserVoted(Auth::user()->id); ?> 20 | 21 | 22 | @endif 23 |
24 |
25 |
26 | 27 |
28 | 29 |
30 |
31 | {{ $snippet->user->name }} 32 | {{ HTML::linkRoute('user.show', $snippet->user->name, $snippet->user->id) }} 33 |

{{ $snippet->created_at->diffForHumans() }}

34 | @if(Auth::check() && Auth::user()->id == $snippet->user_id) 35 | Edit » 36 | @endif 37 |
38 | 39 |
40 | {{ Text::render($snippet->description) }} 41 |
{{{ $snippet->body }}}
42 |
43 |
44 | tags; ?> 45 | @include("partials.tagcloud", ['title' => '']) 46 |
47 |
48 | 49 | @if($snippet->comments->count() || Auth::check()) 50 |
51 | @endif 52 | 53 |
54 |
55 | @if(Auth::check()) 56 | @include('partials.comment_form') 57 | @endif 58 |
59 |
60 | @foreach($snippet->comments as $comment) 61 | @include('partials.comment') 62 | @endforeach 63 |
64 |
65 | 66 |
67 | 68 | @stop 69 | -------------------------------------------------------------------------------- /app/views/layouts/main.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | @yield('title') | vimrcfu 6 | 7 | 8 | 9 | {{ HTML::style('css/font-awesome.css') }} 10 | {{ HTML::style('css/bootstrap.min.css') }} 11 | {{ HTML::style('css/bootstrap-social.css') }} 12 | {{ HTML::style('css/animate.min.css') }} 13 | {{ HTML::style('css/main.css?v=1.2') }} 14 | 18 | 19 | 20 | 21 | @include('partials.navbar') 22 | 23 | @yield('content') 24 | 25 |
26 |
27 |
28 |
29 |

30 | © {{ date('Y') }} Florian Beer - made with Vim
31 | Source code on GitHub
32 | Hosted by 42dev 33 |

34 |

35 | 36 |

37 |
38 |
39 |
40 | 41 | 42 | {{ HTML::script('js/vendor/bootstrap.min.js') }} 43 | {{ HTML::script('js/vendor/wow.min.js') }} 44 | 47 | {{ HTML::script('js/main.js') }} 48 | @yield('script') 49 | @if(getenv('PIWIK_URL')) 50 | @include('partials.tracking') 51 | @endif 52 | 53 | 54 | -------------------------------------------------------------------------------- /bootstrap/start.php: -------------------------------------------------------------------------------- 1 | detectEnvironment(function(){ 28 | 29 | return getenv('APP_ENV') ?: 'local'; 30 | 31 | }); 32 | 33 | /* 34 | |-------------------------------------------------------------------------- 35 | | Bind Paths 36 | |-------------------------------------------------------------------------- 37 | | 38 | | Here we are binding the paths configured in paths.php to the app. You 39 | | should not be changing these here. If you need to change these you 40 | | may do so within the paths.php file and they will be bound here. 41 | | 42 | */ 43 | 44 | $app->bindInstallPaths(require __DIR__.'/paths.php'); 45 | 46 | /* 47 | |-------------------------------------------------------------------------- 48 | | Load The Application 49 | |-------------------------------------------------------------------------- 50 | | 51 | | Here we will load this Illuminate application. We will keep this in a 52 | | separate location so we can isolate the creation of an application 53 | | from the actual running of the application with a given request. 54 | | 55 | */ 56 | 57 | $framework = $app['path.base']. 58 | '/vendor/laravel/framework/src'; 59 | 60 | require $framework.'/Illuminate/Foundation/start.php'; 61 | 62 | /* 63 | |-------------------------------------------------------------------------- 64 | | Return The Application 65 | |-------------------------------------------------------------------------- 66 | | 67 | | This script returns the application instance. The instance is given to 68 | | the calling script so we can separate the building of the instances 69 | | from the actual running of the application and sending responses. 70 | | 71 | */ 72 | 73 | return $app; 74 | -------------------------------------------------------------------------------- /app/filters.php: -------------------------------------------------------------------------------- 1 | setRequestForConsoleEnvironment(); 45 | 46 | $artisan = Illuminate\Console\Application::start($app); 47 | 48 | /* 49 | |-------------------------------------------------------------------------- 50 | | Run The Artisan Application 51 | |-------------------------------------------------------------------------- 52 | | 53 | | When we run the console application, the current CLI command will be 54 | | executed in this console and the response sent back to a terminal 55 | | or another output device for the developers. Here goes nothing! 56 | | 57 | */ 58 | 59 | $status = $artisan->run(); 60 | 61 | /* 62 | |-------------------------------------------------------------------------- 63 | | Shutdown The Application 64 | |-------------------------------------------------------------------------- 65 | | 66 | | Once Artisan has finished running. We will fire off the shutdown events 67 | | so that any final work may be done by the application before we shut 68 | | down the process. This is the last thing to happen to the request. 69 | | 70 | */ 71 | 72 | $app->shutdown(); 73 | 74 | exit($status); 75 | -------------------------------------------------------------------------------- /bootstrap/autoload.php: -------------------------------------------------------------------------------- 1 | beforeFilter('auth', ['only' => ['create', 'store', 'edit', 'update']]); 19 | $this->repository = $repository; 20 | } 21 | 22 | /** 23 | * Displays all Snippets paginated. 24 | * 25 | * @return mixed 26 | */ 27 | public function index() 28 | { 29 | $snippets = $this->repository->snippetsWithCommentsAndUsersPaginated(); 30 | 31 | return View::make('snippets.index', compact('snippets')); 32 | } 33 | 34 | public function hot() 35 | { 36 | $snippets = $this->repository->snippetsWithCommentsAndUsersPaginated('hot'); 37 | 38 | return View::make('snippets.index', compact('snippets')) 39 | ->with('title', 'Hot Snippets'); 40 | } 41 | 42 | /** 43 | * Shows the form for creating a new Snippet. 44 | * 45 | * @return mixed 46 | */ 47 | public function create() 48 | { 49 | return View::make('snippets.create')->withSnippet(new Snippet()); 50 | } 51 | 52 | /** 53 | * Stores a new Snippet. 54 | * 55 | * @return mixed 56 | */ 57 | public function store() 58 | { 59 | $snippet = $this->repository->create(Input::all()); 60 | 61 | return Redirect::route('snippet.show', $snippet->id); 62 | } 63 | 64 | /** 65 | * Displays a Snippet. 66 | * 67 | * @param Vimrcfu\Snippets\Snippet $snippet 68 | * @return mixed 69 | */ 70 | public function show(Snippet $snippet) 71 | { 72 | return View::make('snippets.show', compact('snippet')); 73 | } 74 | 75 | /** 76 | * Shows the form for editing a Snippet. 77 | * 78 | * @param Vimrcfu\Snippets\Snippet $snippet 79 | * @return mixed 80 | */ 81 | public function edit(Snippet $snippet) 82 | { 83 | if ( Auth::user()->id != $snippet->user_id ) 84 | { 85 | return Redirect::home(); 86 | } 87 | 88 | return View::make('snippets.edit', compact('snippet')); 89 | } 90 | 91 | /** 92 | * Updates a Snippet in storage. 93 | * 94 | * @param Vimrcfu\Snippets\Snippet $snippet 95 | * @return mixed 96 | */ 97 | public function update(Snippet $snippet) 98 | { 99 | if ( Auth::user()->id != $snippet->user_id ) 100 | { 101 | return Redirect::home(); 102 | } 103 | 104 | $this->repository->update($snippet, Input::all()); 105 | 106 | return Redirect::route('snippet.show', $snippet->id); 107 | 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /app/views/errors/503.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ $title }} | vimrcfu 6 | 7 | 8 | 9 | {{ HTML::style('css/font-awesome.css') }} 10 | {{ HTML::style('css/bootstrap.min.css') }} 11 | {{ HTML::style('css/bootstrap-social.css') }} 12 | {{ HTML::style('css/animate.min.css') }} 13 | {{ HTML::style('css/main.css?v=1.2') }} 14 | 18 | 19 | 20 | 36 | 37 | 38 |
39 |
40 |

41 | {{ $title }} 42 |

43 | 48 |
49 |
50 | 51 | 52 | 53 | 54 | {{ HTML::script('js/vendor/bootstrap.min.js') }} 55 | {{ HTML::script('js/vendor/wow.min.js') }} 56 | {{ HTML::script('js/snake.js') }} 57 | 60 | {{ HTML::script('js/main.js') }} 61 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /app/config/cache.php: -------------------------------------------------------------------------------- 1 | 'memcached', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | File Cache Location 23 | |-------------------------------------------------------------------------- 24 | | 25 | | When using the "file" cache driver, we need a location where the cache 26 | | files may be stored. A sensible default has been specified, but you 27 | | are free to change it to any other place on disk that you desire. 28 | | 29 | */ 30 | 31 | 'path' => storage_path().'/cache', 32 | 33 | /* 34 | |-------------------------------------------------------------------------- 35 | | Database Cache Connection 36 | |-------------------------------------------------------------------------- 37 | | 38 | | When using the "database" cache driver you may specify the connection 39 | | that should be used to store the cached items. When this option is 40 | | null the default database connection will be utilized for cache. 41 | | 42 | */ 43 | 44 | 'connection' => null, 45 | 46 | /* 47 | |-------------------------------------------------------------------------- 48 | | Database Cache Table 49 | |-------------------------------------------------------------------------- 50 | | 51 | | When using the "database" cache driver we need to know the table that 52 | | should be used to store the cached items. A default table name has 53 | | been provided but you're free to change it however you deem fit. 54 | | 55 | */ 56 | 57 | 'table' => 'cache', 58 | 59 | /* 60 | |-------------------------------------------------------------------------- 61 | | Memcached Servers 62 | |-------------------------------------------------------------------------- 63 | | 64 | | Now you may specify an array of your Memcached servers that should be 65 | | used when utilizing the Memcached cache driver. All of the servers 66 | | should contain a value for "host", "port", and "weight" options. 67 | | 68 | */ 69 | 70 | 'memcached' => array( 71 | 72 | array('host' => '127.0.0.1', 'port' => 11211, 'weight' => 100), 73 | 74 | ), 75 | 76 | /* 77 | |-------------------------------------------------------------------------- 78 | | Cache Key Prefix 79 | |-------------------------------------------------------------------------- 80 | | 81 | | When utilizing a RAM based store such as APC or Memcached, there might 82 | | be other applications utilizing the same cache. So, we'll specify a 83 | | value to get prefixed to all our keys so we can avoid collisions. 84 | | 85 | */ 86 | 87 | 'prefix' => 'vimrcfu', 88 | 89 | ); 90 | -------------------------------------------------------------------------------- /app/controllers/UsersController.php: -------------------------------------------------------------------------------- 1 | repository = $repository; 18 | } 19 | 20 | /** 21 | * Persist new User with GitHub data then log in. 22 | * 23 | * @return mixed 24 | */ 25 | public function login() 26 | { 27 | $code = Request::get('code'); 28 | $github = OAuth::consumer('GitHub'); 29 | 30 | if ( ! empty($code)) 31 | { 32 | $token = $github->requestAccessToken($code); 33 | $result = json_decode($github->request('user'), true); 34 | 35 | if ( empty($result['name']) ) 36 | { 37 | $result['name'] = $result['login']; 38 | } 39 | 40 | $result['email'] = last(json_decode($github->request('user/emails'), true)); 41 | 42 | $githubData = [ 43 | 'github_id' => $result['id'], 44 | 'github_url' => $result['html_url'], 45 | 'avatar_url' => $result['avatar_url'], 46 | 'email' => $result['email'], 47 | 'name' => $result['name'] 48 | ]; 49 | 50 | Auth::login($this->repository->findOrCreate($githubData)); 51 | 52 | return Redirect::intended(); 53 | } 54 | 55 | return Redirect::to((string) OAuth::consumer('GitHub')->getAuthorizationUri()); 56 | } 57 | 58 | /** 59 | * Log out User. 60 | * 61 | * @return mixed 62 | */ 63 | public function logout() 64 | { 65 | Auth::logout(); 66 | 67 | return Redirect::home(); 68 | } 69 | 70 | /** 71 | * Shows a User with all Tags and paginated Snippets. 72 | * 73 | * @param Vimrcfu\Users\User $user 74 | * @return mixed 75 | */ 76 | public function show($user) 77 | { 78 | $snippetsResult = $user->snippets(); 79 | $total = $snippetsResult->count(); 80 | $snippets = $snippetsResult->with('comments')->simplePaginate(10); 81 | $tags = $user->tags(); 82 | 83 | return View::make('users.show', compact('user', 'snippets', 'total', 'tags')); 84 | } 85 | 86 | /** 87 | * Shows a User's upvoted Snippets 88 | * 89 | * @param Vimrcfu\Users\User $user 90 | * @return mixed 91 | */ 92 | public function upvotes($user) 93 | { 94 | $snippetsResult = Vimrcfu\Snippets\Snippet::select('snippets.*') 95 | ->where('user_id', '!=', $user->id) 96 | ->whereHas('votes', function ($q) use ($user) { 97 | $q->where('user_id', $user->id) 98 | ->where('score', '=', '1'); 99 | })->orderBy('created_at', 'DESC'); 100 | $total = $user->snippets()->count(); 101 | $snippets = $snippetsResult->simplePaginate(10); 102 | $tags = $user->tags(); 103 | 104 | return View::make('users.show', compact('user', 'snippets', 'total', 'tags')); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /app/start/global.php: -------------------------------------------------------------------------------- 1 | withErrors($exception->getErrors()) 58 | ->withInput(); 59 | }); 60 | 61 | App::missing(function($exception) 62 | { 63 | return Response::view('errors.404', array(), 404); 64 | }); 65 | 66 | /* 67 | |-------------------------------------------------------------------------- 68 | | Maintenance Mode Handler 69 | |-------------------------------------------------------------------------- 70 | | 71 | | The "down" Artisan command gives you the ability to put an application 72 | | into maintenance mode. Here, you will define what is displayed back 73 | | to the user if maintenance mode is in effect for the application. 74 | | 75 | */ 76 | 77 | App::down(function() 78 | { 79 | return Response::view('errors.503', ['title' => 'Down for maintenance'], 503); 80 | }); 81 | 82 | /* 83 | |-------------------------------------------------------------------------- 84 | | Require The Filters File 85 | |-------------------------------------------------------------------------- 86 | | 87 | | Next we will load the filters file for the application. This gives us 88 | | a nice separate location to store our route and application filter 89 | | definitions instead of putting them all in the main routes file. 90 | | 91 | */ 92 | 93 | require app_path().'/filters.php'; 94 | -------------------------------------------------------------------------------- /app/Vimrcfu/Core/Text.php: -------------------------------------------------------------------------------- 1 | ))\/?.*?>/"; 16 | 17 | return preg_replace($regex, '', $text); 18 | } 19 | 20 | /** 21 | * Creates clickable links from URLs. 22 | * 23 | * @param string $text 24 | * @return string 25 | */ 26 | private function createExternalLinks($text) 27 | { 28 | $regex = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,63}([\w\.\/:\=\?\#\!-]*)/"; 29 | 30 | return preg_replace($regex, '$0', $text); 31 | } 32 | 33 | /** 34 | * Constructs clickable internal links to Snippets. 35 | * 36 | * @param string $text 37 | * @param bool $absolute 38 | * @return string 39 | */ 40 | private function createSnippetLinks($text, $absolute = false) 41 | { 42 | $regex = "/snippet#([0-9]*)(\/\S*)?/"; 43 | if ( $absolute ) 44 | { 45 | return preg_replace($regex, 'Snippet #$1', $text); 46 | } 47 | 48 | return preg_replace($regex, 'Snippet #$1', $text); 49 | } 50 | 51 | /** 52 | * Returns HTML from Markdown 53 | * 54 | * @param string $text 55 | * @return string 56 | */ 57 | private function renderMarkdown($text) 58 | { 59 | return MarkdownExtra::defaultTransform($text); 60 | } 61 | 62 | /** 63 | * Returns HTML without unwanted tags 64 | * with external and internal links. 65 | * 66 | * @param string $text 67 | * @return string 68 | */ 69 | public function render($text) 70 | { 71 | $text = $this->renderMarkdown($text); 72 | $text = $this->stripTags($text); 73 | $text = $this->createExternalLinks($text); 74 | $text = $this->createSnippetLinks($text); 75 | 76 | return $text; 77 | } 78 | 79 | /** 80 | * Returns HTML from Markdown file with all tags intact. 81 | * 82 | * @param string $filename 83 | * @return string 84 | */ 85 | public function renderInclude($filename) 86 | { 87 | $text = \File::get(app_path().'/markdown/'.$filename.'.md'); 88 | $text = $this->renderMarkdown($text); 89 | $text = $this->createSnippetLinks($text); 90 | 91 | return $text; 92 | } 93 | 94 | /** 95 | * Returns rendered HTML with absolute links for RSS. 96 | * 97 | * @param string $text 98 | * @return string 99 | */ 100 | public function renderForRss($text) 101 | { 102 | $text = $this->renderMarkdown($text); 103 | $text = $this->stripTags($text); 104 | $text = $this->createExternalLinks($text); 105 | $text = $this->createSnippetLinks($text, true); 106 | 107 | return $text; 108 | } 109 | 110 | /** 111 | * Escape special characters for XML output. 112 | * 113 | * @param string $text 114 | * @return string 115 | */ 116 | public function xmlentities($text) 117 | { 118 | $text = str_replace('&', '&', $text); 119 | $text = str_replace('<', '<', $text); 120 | $text = str_replace('>', '>', $text); 121 | 122 | return $text; 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /public/js/snake.js: -------------------------------------------------------------------------------- 1 | // Snake game from: http://thecodeplayer.com/walkthrough/html5-game-tutorial-make-a-snake-game-using-html5-canvas-jquery 2 | 3 | $(document).ready(function(){ 4 | var canvas = $("#canvas")[0]; 5 | var ctx = canvas.getContext("2d"); 6 | var w = $("#canvas").width(); 7 | var h = $("#canvas").height(); 8 | var cw = 10; 9 | var d; 10 | var food; 11 | var score; 12 | var snake_array; 13 | 14 | function init() 15 | { 16 | d = "right"; 17 | create_snake(); 18 | create_food(); 19 | score = 0; 20 | if(typeof game_loop != "undefined") clearInterval(game_loop); 21 | game_loop = setInterval(paint, 60); 22 | } 23 | init(); 24 | 25 | function create_snake() 26 | { 27 | var length = 5; 28 | snake_array = []; 29 | for(var i = length-1; i>=0; i--) 30 | { 31 | snake_array.push({x: i, y:0}); 32 | } 33 | } 34 | 35 | function create_food() 36 | { 37 | food = { 38 | x: Math.round(Math.random()*(w-cw)/cw), 39 | y: Math.round(Math.random()*(h-cw)/cw), 40 | }; 41 | } 42 | 43 | function paint() 44 | { 45 | ctx.fillStyle = "rgba(0, 0, 0, 0.5)"; 46 | ctx.fillRect(0, 0, w, h); 47 | ctx.strokeStyle = "rgb(97, 95, 56)"; 48 | ctx.strokeRect(0, 0, w, h); 49 | 50 | var nx = snake_array[0].x; 51 | var ny = snake_array[0].y; 52 | if(d == "right") nx++; 53 | else if(d == "left") nx--; 54 | else if(d == "up") ny--; 55 | else if(d == "down") ny++; 56 | 57 | if(nx == -1 || nx == w/cw || ny == -1 || ny == h/cw || check_collision(nx, ny, snake_array)) 58 | { 59 | init(); 60 | return; 61 | } 62 | 63 | if(nx == food.x && ny == food.y) 64 | { 65 | var tail = {x: nx, y: ny}; 66 | score++; 67 | create_food(); 68 | } 69 | else 70 | { 71 | var tail = snake_array.pop(); 72 | tail.x = nx; tail.y = ny; 73 | } 74 | 75 | snake_array.unshift(tail); 76 | 77 | for(var i = 0; i < snake_array.length; i++) 78 | { 79 | var c = snake_array[i]; 80 | paint_cell(c.x, c.y); 81 | } 82 | 83 | paint_cell(food.x, food.y); 84 | var score_text = "Score: " + score; 85 | ctx.fillText(score_text, 5, h-5); 86 | } 87 | 88 | function paint_cell(x, y) 89 | { 90 | ctx.fillStyle = "rgb(97, 95, 56)"; 91 | ctx.fillRect(x*cw, y*cw, cw, cw); 92 | ctx.strokeStyle = "black"; 93 | ctx.strokeRect(x*cw, y*cw, cw, cw); 94 | } 95 | 96 | function check_collision(x, y, array) 97 | { 98 | for(var i = 0; i < array.length; i++) 99 | { 100 | if(array[i].x == x && array[i].y == y) 101 | return true; 102 | } 103 | return false; 104 | } 105 | 106 | $(document).keydown(function(e){ 107 | var key = e.which; 108 | if(key == "37" && d != "right") d = "left"; 109 | else if(key == "38" && d != "down") d = "up"; 110 | else if(key == "39" && d != "left") d = "right"; 111 | else if(key == "40" && d != "up") d = "down"; 112 | }); 113 | }); 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vimrcfu 2 | 3 | http://vimrcfu.com 4 | 5 | Made with [Laravel 4.2](http://laravel.com/docs/4.2) 6 | 7 | --- 8 | 9 | ## Set up 10 | 11 | * Clone the repository into a directory on your local machine (development) or server (production) 12 | * Follow the [configuration](#Configuration) steps below 13 | * **vimrcfu** uses Memcache for caching. If you don't want to install Memcache, set driver to `file` in `app/config/cache.php`. 14 | * Run `composer install` 15 | * Run `php artisan migrate` 16 | * Don't forget to smile once in a while! 17 | 18 | 19 | ## Configuration 20 | 21 | ### For development 22 | 23 | * Create a [GitHub application](https://github.com/settings/applications), for example "vimrcfu dev", with your local Homepage URL and Authorization callback URL (e.g. `http://vimrcfu.loc` and `http://vimrcfu.loc/login`) and note the Client ID and Client Secret GitHub generates for your. 24 | * Create the file `.env.local.php` in the directory where you cloned the repository with the following content: 25 | 26 | ``` php 27 | return [ 28 | 'DB_HOST' => 'localhost', # Fill in your database host 29 | 'DB_NAME' => 'vimrcfu', # Fill in your database name 30 | 'DB_USER' => 'root', # Fill in your database username 31 | 'DB_PASSWORD' => '', # Fill in your database password 32 | 'APP_KEY' => '', # Choose a very random string with at least 32 characters 33 | 'GITHUB_CLIENT' => '', # Fill in your GitHub Client ID 34 | 'GITHUB_SECRET' => '', # Fill in your GitHub Client Secret 35 | 'PIWIK_URL' => '', # Fill in URL if you want Piwik tracking 36 | 'PIWIK_ID' => '', # Piwik site id 37 | ]; 38 | ``` 39 | 40 | ### For production 41 | 42 | * In your webserver set an environment variable called `APP_ENV` and give it a value of `production`. 43 | 44 | * For Apache put the following in your vhost configuration: `SetEnv APP_ENV production` 45 | * For nginx if you use php-fpm put the following in your location block: `fastcgi_param APP_ENV production;` 46 | 47 | 48 | * Create the file `.env.php` in the directory where you cloned the repository with the same contents as above, but fill in your production database settings, Client ID and Client Secret (create a new application on GitHub with the actual Homepage URL and Authorization callback URL for your production domain). 49 | 50 | ## Maintainer 51 | 52 | **vimrcfu** is currently maintained by [Florian Beer](http://github.com/florianbeer). If you have any questions please don't hesitate to get in touch. 53 | 54 | The best way to ask questions is via GitHub [issues](https://github.com/florianbeer/vimrcfu/issues) or via Twitter [@azath0th](https://twitter.com/azath0th). 55 | 56 | ## Contributing 57 | 58 | Please see [CONTRIBUTING](https://github.com/florianbeer/vimrcfu/blob/master/CONTRIBUTING.md) for details. 59 | 60 | ## License 61 | 62 | Creative Commons License
vimrcfu by Florian Beer | 42dev is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. 63 | 64 | Please see [LICENSE](https://github.com/florianbeer/vimrcfu/blob/master/LICENSE.md) for more details. 65 | 66 | -------------------------------------------------------------------------------- /app/config/database.php: -------------------------------------------------------------------------------- 1 | PDO::FETCH_CLASS, 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Default Database Connection Name 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may specify which of the database connections below you wish 24 | | to use as your default connection for all database work. Of course 25 | | you may use many connections at once using the Database library. 26 | | 27 | */ 28 | 29 | 'default' => 'mysql', 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Database Connections 34 | |-------------------------------------------------------------------------- 35 | | 36 | | Here are each of the database connections setup for your application. 37 | | Of course, examples of configuring each database platform that is 38 | | supported by Laravel is shown below to make development simple. 39 | | 40 | | 41 | | All database work in Laravel is done through the PHP PDO facilities 42 | | so make sure you have the driver for your particular database of 43 | | choice installed on your machine before you begin development. 44 | | 45 | */ 46 | 47 | 'connections' => array( 48 | 49 | 'sqlite' => array( 50 | 'driver' => 'sqlite', 51 | 'database' => __DIR__.'/../database/production.sqlite', 52 | 'prefix' => '', 53 | ), 54 | 55 | 'mysql' => array( 56 | 'driver' => 'mysql', 57 | 'host' => getenv('DB_HOST'), 58 | 'database' => getenv('DB_NAME'), 59 | 'username' => getenv('DB_USER'), 60 | 'password' => getenv('DB_PASSWORD'), 61 | 'charset' => 'utf8', 62 | 'collation' => 'utf8_unicode_ci', 63 | 'prefix' => '', 64 | ), 65 | 66 | 'pgsql' => array( 67 | 'driver' => 'pgsql', 68 | 'host' => 'localhost', 69 | 'database' => 'forge', 70 | 'username' => 'forge', 71 | 'password' => '', 72 | 'charset' => 'utf8', 73 | 'prefix' => '', 74 | 'schema' => 'public', 75 | ), 76 | 77 | 'sqlsrv' => array( 78 | 'driver' => 'sqlsrv', 79 | 'host' => 'localhost', 80 | 'database' => 'database', 81 | 'username' => 'root', 82 | 'password' => '', 83 | 'prefix' => '', 84 | ), 85 | 86 | ), 87 | 88 | /* 89 | |-------------------------------------------------------------------------- 90 | | Migration Repository Table 91 | |-------------------------------------------------------------------------- 92 | | 93 | | This table keeps track of all the migrations that have already run for 94 | | your application. Using this information, we can determine which of 95 | | the migrations on disk haven't actually been run in the database. 96 | | 97 | */ 98 | 99 | 'migrations' => 'migrations', 100 | 101 | /* 102 | |-------------------------------------------------------------------------- 103 | | Redis Databases 104 | |-------------------------------------------------------------------------- 105 | | 106 | | Redis is an open source, fast, and advanced key-value store that also 107 | | provides a richer set of commands than a typical key-value systems 108 | | such as APC or Memcached. Laravel makes it easy to dig right in. 109 | | 110 | */ 111 | 112 | 'redis' => array( 113 | 114 | 'cluster' => false, 115 | 116 | 'default' => array( 117 | 'host' => '127.0.0.1', 118 | 'port' => 6379, 119 | 'database' => 0, 120 | ), 121 | 122 | ), 123 | 124 | ); 125 | -------------------------------------------------------------------------------- /app/config/mail.php: -------------------------------------------------------------------------------- 1 | 'smtp', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | SMTP Host Address 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may provide the host address of the SMTP server used by your 26 | | applications. A default option is provided that is compatible with 27 | | the Mailgun mail service which will provide reliable deliveries. 28 | | 29 | */ 30 | 31 | 'host' => 'smtp.mailgun.org', 32 | 33 | /* 34 | |-------------------------------------------------------------------------- 35 | | SMTP Host Port 36 | |-------------------------------------------------------------------------- 37 | | 38 | | This is the SMTP port used by your application to deliver e-mails to 39 | | users of the application. Like the host we have set this value to 40 | | stay compatible with the Mailgun e-mail application by default. 41 | | 42 | */ 43 | 44 | 'port' => 587, 45 | 46 | /* 47 | |-------------------------------------------------------------------------- 48 | | Global "From" Address 49 | |-------------------------------------------------------------------------- 50 | | 51 | | You may wish for all e-mails sent by your application to be sent from 52 | | the same address. Here, you may specify a name and address that is 53 | | used globally for all e-mails that are sent by your application. 54 | | 55 | */ 56 | 57 | 'from' => array('address' => null, 'name' => null), 58 | 59 | /* 60 | |-------------------------------------------------------------------------- 61 | | E-Mail Encryption Protocol 62 | |-------------------------------------------------------------------------- 63 | | 64 | | Here you may specify the encryption protocol that should be used when 65 | | the application send e-mail messages. A sensible default using the 66 | | transport layer security protocol should provide great security. 67 | | 68 | */ 69 | 70 | 'encryption' => 'tls', 71 | 72 | /* 73 | |-------------------------------------------------------------------------- 74 | | SMTP Server Username 75 | |-------------------------------------------------------------------------- 76 | | 77 | | If your SMTP server requires a username for authentication, you should 78 | | set it here. This will get used to authenticate with your server on 79 | | connection. You may also set the "password" value below this one. 80 | | 81 | */ 82 | 83 | 'username' => null, 84 | 85 | /* 86 | |-------------------------------------------------------------------------- 87 | | SMTP Server Password 88 | |-------------------------------------------------------------------------- 89 | | 90 | | Here you may set the password required by your SMTP server to send out 91 | | messages from your application. This will be given to the server on 92 | | connection so that the application will be able to send messages. 93 | | 94 | */ 95 | 96 | 'password' => null, 97 | 98 | /* 99 | |-------------------------------------------------------------------------- 100 | | Sendmail System Path 101 | |-------------------------------------------------------------------------- 102 | | 103 | | When using the "sendmail" driver to send e-mails, we will need to know 104 | | the path to where Sendmail lives on this server. A default path has 105 | | been provided here, which will work well on most of your systems. 106 | | 107 | */ 108 | 109 | 'sendmail' => '/usr/sbin/sendmail -bs', 110 | 111 | /* 112 | |-------------------------------------------------------------------------- 113 | | Mail "Pretend" 114 | |-------------------------------------------------------------------------- 115 | | 116 | | When this option is enabled, e-mail will not actually be sent over the 117 | | web and will instead be written to your application's logs files so 118 | | you may inspect the message. This is great for local development. 119 | | 120 | */ 121 | 122 | 'pretend' => false, 123 | 124 | ); 125 | -------------------------------------------------------------------------------- /app/config/session.php: -------------------------------------------------------------------------------- 1 | 'memcached', 20 | 21 | /* 22 | |-------------------------------------------------------------------------- 23 | | Session Lifetime 24 | |-------------------------------------------------------------------------- 25 | | 26 | | Here you may specify the number of minutes that you wish the session 27 | | to be allowed to remain idle before it expires. If you want them 28 | | to immediately expire on the browser closing, set that option. 29 | | 30 | */ 31 | 32 | 'lifetime' => 129600, 33 | 34 | 'expire_on_close' => false, 35 | 36 | /* 37 | |-------------------------------------------------------------------------- 38 | | Session File Location 39 | |-------------------------------------------------------------------------- 40 | | 41 | | When using the native session driver, we need a location where session 42 | | files may be stored. A default has been set for you but a different 43 | | location may be specified. This is only needed for file sessions. 44 | | 45 | */ 46 | 47 | 'files' => storage_path().'/sessions', 48 | 49 | /* 50 | |-------------------------------------------------------------------------- 51 | | Session Database Connection 52 | |-------------------------------------------------------------------------- 53 | | 54 | | When using the "database" or "redis" session drivers, you may specify a 55 | | connection that should be used to manage these sessions. This should 56 | | correspond to a connection in your database configuration options. 57 | | 58 | */ 59 | 60 | 'connection' => null, 61 | 62 | /* 63 | |-------------------------------------------------------------------------- 64 | | Session Database Table 65 | |-------------------------------------------------------------------------- 66 | | 67 | | When using the "database" session driver, you may specify the table we 68 | | should use to manage the sessions. Of course, a sensible default is 69 | | provided for you; however, you are free to change this as needed. 70 | | 71 | */ 72 | 73 | 'table' => 'sessions', 74 | 75 | /* 76 | |-------------------------------------------------------------------------- 77 | | Session Sweeping Lottery 78 | |-------------------------------------------------------------------------- 79 | | 80 | | Some session drivers must manually sweep their storage location to get 81 | | rid of old sessions from storage. Here are the chances that it will 82 | | happen on a given request. By default, the odds are 2 out of 100. 83 | | 84 | */ 85 | 86 | 'lottery' => array(2, 100), 87 | 88 | /* 89 | |-------------------------------------------------------------------------- 90 | | Session Cookie Name 91 | |-------------------------------------------------------------------------- 92 | | 93 | | Here you may change the name of the cookie used to identify a session 94 | | instance by ID. The name specified here will get used every time a 95 | | new session cookie is created by the framework for every driver. 96 | | 97 | */ 98 | 99 | 'cookie' => 'get_your_vimrc_fu_on', 100 | 101 | /* 102 | |-------------------------------------------------------------------------- 103 | | Session Cookie Path 104 | |-------------------------------------------------------------------------- 105 | | 106 | | The session cookie path determines the path for which the cookie will 107 | | be regarded as available. Typically, this will be the root path of 108 | | your application but you are free to change this when necessary. 109 | | 110 | */ 111 | 112 | 'path' => '/', 113 | 114 | /* 115 | |-------------------------------------------------------------------------- 116 | | Session Cookie Domain 117 | |-------------------------------------------------------------------------- 118 | | 119 | | Here you may change the domain of the cookie used to identify a session 120 | | in your application. This will determine which domains the cookie is 121 | | available to in your application. A sensible default has been set. 122 | | 123 | */ 124 | 125 | 'domain' => null, 126 | 127 | /* 128 | |-------------------------------------------------------------------------- 129 | | HTTPS Only Cookies 130 | |-------------------------------------------------------------------------- 131 | | 132 | | By setting this option to true, session cookies will only be sent back 133 | | to the server if the browser has a HTTPS connection. This will keep 134 | | the cookie from being sent to you if it can not be done securely. 135 | | 136 | */ 137 | 138 | 'secure' => false, 139 | 140 | ); 141 | -------------------------------------------------------------------------------- /app/Vimrcfu/Snippets/EloquentSnippetsRepository.php: -------------------------------------------------------------------------------- 1 | validator = $validator; 29 | $this->tagsRepository = $tagsRepository; 30 | } 31 | 32 | /** 33 | * @var string 34 | * @return mixed 35 | */ 36 | public function snippetsWithCommentsAndUsersPaginated($order = null) 37 | { 38 | switch ($order) 39 | { 40 | case 'hot': 41 | return Snippet::select('snippets.*') 42 | ->rightJoin('votes', 'votes.snippet_id', '=', 'snippets.id') 43 | ->orderBy(DB::raw('sum(score)'), 'DESC') 44 | ->orderBy('snippets.created_at', 'DESC') 45 | ->groupBy('snippets.id') 46 | ->havingRaw('sum(score) > 1') 47 | ->with('comments', 'user') 48 | ->paginate(10); 49 | break; 50 | default: 51 | return Snippet::with('comments', 'user')->orderBy('id', 'DESC')->paginate(10); 52 | break; 53 | } 54 | 55 | } 56 | 57 | /** 58 | * @return mixed 59 | */ 60 | public function snippetsForFeed() 61 | { 62 | return Snippet::with('user')->orderBy('id', 'desc')->take(20)->get(); 63 | } 64 | 65 | /** 66 | * @return mixed 67 | */ 68 | public function newSnippets() 69 | { 70 | return Snippet::with('comments', 'user')->orderBy('id', 'DESC')->take(5)->get(); 71 | } 72 | 73 | /** 74 | * @return mixed 75 | */ 76 | public function topSnippet() 77 | { 78 | return Cache::remember('topSnippet', 5, function () 79 | { 80 | $topSnippetResult = DB::select(DB::raw(' 81 | SELECT snippets.id, sum(votes.score) points FROM snippets 82 | JOIN votes ON snippets.id = votes.snippet_id 83 | GROUP BY snippets.id ORDER BY points DESC, snippets.id DESC LIMIT 1' 84 | )); 85 | 86 | return (isset($topSnippetResult[0])) ? $topSnippetResult[0] : new Snippet(); 87 | }); 88 | } 89 | 90 | /** 91 | * @return mixed 92 | */ 93 | public function topCommented() 94 | { 95 | return Cache::remember('topComment', 5, function () 96 | { 97 | $topCommentResult = DB::select(DB::raw(' 98 | SELECT snippets.id, count(comments.id) comments_count FROM snippets 99 | JOIN comments ON snippets.id = comments.snippet_id 100 | GROUP BY snippet_id ORDER BY comments_count DESC LIMIT 1' 101 | )); 102 | 103 | return (isset($topCommentResult[0])) ? $topCommentResult[0] : new Comment(); 104 | }); 105 | } 106 | 107 | /** 108 | * @param array $input 109 | * @return mixed 110 | */ 111 | public function create($input) 112 | { 113 | $this->validator->validate($input); 114 | $snippet = new Snippet(); 115 | $snippet->title = $input['title']; 116 | $snippet->body = $input['body']; 117 | $snippet->description = $input['description']; 118 | $snippet->user_id = Auth::user()->id; 119 | $snippet->save(); 120 | 121 | $this->tagsRepository->updateTags($snippet, $input['tags']); 122 | 123 | $vote = new Vote(); 124 | $vote->user_id = Auth::user()->id; 125 | $vote->snippet_id = $snippet->id; 126 | $vote->score = 1; 127 | $vote->save(); 128 | 129 | return $snippet; 130 | } 131 | 132 | /** 133 | * @param Vimrcfu\Snippets\Snippet $snippet 134 | * @param array $input 135 | * @return mixed 136 | */ 137 | public function update(Snippet $snippet, $input) 138 | { 139 | $this->validator->validate($input); 140 | 141 | $snippet->title = $input['title']; 142 | $snippet->body = $input['body']; 143 | $snippet->description = $input['description']; 144 | $snippet->save(); 145 | 146 | $this->tagsRepository->updateTags($snippet, $input['tags']); 147 | 148 | return $snippet; 149 | } 150 | 151 | /** 152 | * @param string $search 153 | * @return array 154 | */ 155 | public function fulltextSearch($search) { 156 | // Need to use simplePaginate() here and then run 157 | // an extra count() query because Laravel 2.4's Paginator class 158 | // cannot determine the correct total number automatically in this case. 159 | $items = Snippet::whereRaw('MATCH(title,description,body) AGAINST(? IN BOOLEAN MODE)') 160 | ->select('*') 161 | ->addSelect( DB::raw('MATCH (title) AGAINST(?) title_relevance') ) 162 | ->addSelect( DB::raw('MATCH (title,description,body) AGAINST (?) relevance') ) 163 | ->setBindings([$search,$search,$search]) 164 | ->orderBy('title_relevance', 'desc') 165 | ->orderBy('relevance', 'desc') 166 | ->with('comments', 'user') 167 | ->simplePaginate(10); 168 | 169 | $total = Snippet::whereRaw('MATCH(title,description,body) AGAINST(? IN BOOLEAN MODE)', [$search])->count(); 170 | 171 | return [ 172 | 'items' => $items, 173 | 'total' => $total 174 | ]; 175 | } 176 | 177 | } 178 | -------------------------------------------------------------------------------- /app/lang/en/validation.php: -------------------------------------------------------------------------------- 1 | "The :attribute must be accepted.", 17 | "active_url" => "The :attribute is not a valid URL.", 18 | "after" => "The :attribute must be a date after :date.", 19 | "alpha" => "The :attribute may only contain letters.", 20 | "alpha_dash" => "The :attribute may only contain letters, numbers, and dashes.", 21 | "alpha_num" => "The :attribute may only contain letters and numbers.", 22 | "array" => "The :attribute must be an array.", 23 | "before" => "The :attribute must be a date before :date.", 24 | "between" => array( 25 | "numeric" => "The :attribute must be between :min and :max.", 26 | "file" => "The :attribute must be between :min and :max kilobytes.", 27 | "string" => "The :attribute must be between :min and :max characters.", 28 | "array" => "The :attribute must have between :min and :max items.", 29 | ), 30 | "boolean" => "The :attribute field must be true or false.", 31 | "confirmed" => "The :attribute confirmation does not match.", 32 | "date" => "The :attribute is not a valid date.", 33 | "date_format" => "The :attribute does not match the format :format.", 34 | "different" => "The :attribute and :other must be different.", 35 | "digits" => "The :attribute must be :digits digits.", 36 | "digits_between" => "The :attribute must be between :min and :max digits.", 37 | "email" => "The :attribute must be a valid email address.", 38 | "exists" => "The selected :attribute is invalid.", 39 | "image" => "The :attribute must be an image.", 40 | "in" => "The selected :attribute is invalid.", 41 | "integer" => "The :attribute must be an integer.", 42 | "ip" => "The :attribute must be a valid IP address.", 43 | "max" => array( 44 | "numeric" => "The :attribute may not be greater than :max.", 45 | "file" => "The :attribute may not be greater than :max kilobytes.", 46 | "string" => "The :attribute may not be greater than :max characters.", 47 | "array" => "The :attribute may not have more than :max items.", 48 | ), 49 | "mimes" => "The :attribute must be a file of type: :values.", 50 | "min" => array( 51 | "numeric" => "The :attribute must be at least :min.", 52 | "file" => "The :attribute must be at least :min kilobytes.", 53 | "string" => "The :attribute must be at least :min characters.", 54 | "array" => "The :attribute must have at least :min items.", 55 | ), 56 | "not_in" => "The selected :attribute is invalid.", 57 | "numeric" => "The :attribute must be a number.", 58 | "regex" => "The :attribute format is invalid.", 59 | "required" => "The :attribute field is required.", 60 | "required_if" => "The :attribute field is required when :other is :value.", 61 | "required_with" => "The :attribute field is required when :values is present.", 62 | "required_with_all" => "The :attribute field is required when :values is present.", 63 | "required_without" => "The :attribute field is required when :values is not present.", 64 | "required_without_all" => "The :attribute field is required when none of :values are present.", 65 | "same" => "The :attribute and :other must match.", 66 | "size" => array( 67 | "numeric" => "The :attribute must be :size.", 68 | "file" => "The :attribute must be :size kilobytes.", 69 | "string" => "The :attribute must be :size characters.", 70 | "array" => "The :attribute must contain :size items.", 71 | ), 72 | "unique" => "The :attribute has already been taken.", 73 | "url" => "The :attribute format is invalid.", 74 | "timezone" => "The :attribute must be a valid zone.", 75 | 76 | /* 77 | |-------------------------------------------------------------------------- 78 | | Custom Validation Language Lines 79 | |-------------------------------------------------------------------------- 80 | | 81 | | Here you may specify custom validation messages for attributes using the 82 | | convention "attribute.rule" to name the lines. This makes it quick to 83 | | specify a specific custom language line for a given attribute rule. 84 | | 85 | */ 86 | 87 | 'custom' => array( 88 | 'attribute-name' => array( 89 | 'rule-name' => 'custom-message', 90 | ), 91 | ), 92 | 93 | /* 94 | |-------------------------------------------------------------------------- 95 | | Custom Validation Attributes 96 | |-------------------------------------------------------------------------- 97 | | 98 | | The following language lines are used to swap attribute place-holders 99 | | with something more reader friendly such as E-Mail Address instead 100 | | of "email". This simply helps us make messages a little cleaner. 101 | | 102 | */ 103 | 104 | 'attributes' => array(), 105 | 106 | ); 107 | -------------------------------------------------------------------------------- /public/css/main.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | padding-top: 50px; 4 | padding-bottom: 20px; 5 | } 6 | 7 | a 8 | { 9 | transition: all .2s ease-in; 10 | } 11 | 12 | a:hover, a:focus 13 | { 14 | color: #17467b; 15 | text-decoration: none; 16 | } 17 | 18 | a.navbar-brand 19 | { 20 | font-family: Courier, monospace; 21 | } 22 | 23 | .wow 24 | { 25 | visibility: hidden; 26 | } 27 | 28 | .jumbotron 29 | { 30 | background: url('../img/home_bg.png') no-repeat top left fixed; 31 | background-size: cover; 32 | color: white; 33 | } 34 | 35 | .jumbotron h1 36 | { 37 | letter-spacing: -3px; 38 | } 39 | 40 | .snippet-box 41 | { 42 | margin-bottom: 10px; 43 | min-height: 110px; 44 | } 45 | 46 | .snippet-box h3 47 | { 48 | margin-top: 0; 49 | word-wrap: break-word; 50 | -webkit-hyphens: auto; 51 | -moz-hyphens: auto; 52 | hyphens: auto; 53 | } 54 | 55 | textarea.snippet 56 | { 57 | font-family: "Courier"; 58 | } 59 | 60 | .comment-box 61 | { 62 | padding: 10px 0; 63 | overflow: auto; 64 | } 65 | 66 | .comment-box:nth-child(odd) 67 | { 68 | background: rgba(28,120,220,.1); 69 | } 70 | 71 | .comment-box blockquote 72 | { 73 | font-size: 0.9em; 74 | } 75 | 76 | /* block code */ 77 | .comment-box code 78 | { 79 | display: block; 80 | white-space: pre; 81 | overflow: auto; 82 | } 83 | 84 | /* inline code */ 85 | .comment-box p code 86 | { 87 | display: inline; 88 | white-space: pre-line; 89 | } 90 | 91 | .comment-form 92 | { 93 | margin-bottom: 20px; 94 | } 95 | 96 | abbr 97 | { 98 | font-style: italic; 99 | } 100 | 101 | img.img-profile 102 | { 103 | max-width: 100px; 104 | max-height: 100px; 105 | float: left; 106 | margin-right: 10px; 107 | margin-bottom: 25px; 108 | } 109 | 110 | img.rounded 111 | { 112 | border: 5px solid #ddd; 113 | border-radius: 5em; 114 | } 115 | 116 | .score 117 | { 118 | margin-top: 21px; 119 | margin-bottom:10.5px; 120 | line-height: 1.1; 121 | font-size: 39px; 122 | font-family: "Source Sans Pro",Calibri,Candara,Arial,sans-serif; 123 | font-weight: 300; 124 | } 125 | 126 | .votelink:hover 127 | { 128 | cursor: text; 129 | color: #2780e3; 130 | } 131 | 132 | .dark 133 | { 134 | color: #999; 135 | } 136 | 137 | .dark:hover 138 | { 139 | cursor: pointer; 140 | color: #2780e3; 141 | } 142 | 143 | .hidden 144 | { 145 | position: absolute; 146 | left: -200em; 147 | } 148 | 149 | .toggle-visibility 150 | { 151 | cursor: pointer; 152 | border-bottom: 1px dotted; 153 | } 154 | 155 | kbd 156 | { 157 | color: #000; 158 | background: #eee; 159 | border-style: solid; 160 | border-color: #ccc #aaa #888 #bbb; 161 | padding: .1em .6em; 162 | border: 1px solid #ccc; 163 | font-size: 11px; 164 | background-color: #f7f7f7; 165 | color: #333; 166 | -moz-box-shadow: 0 1px 0 rgba(0,0,0,0.2),0 0 0 2px #fff inset; 167 | -webkit-box-shadow: 0 1px 0 rgba(0,0,0,0.2),0 0 0 2px #fff inset; 168 | box-shadow: 0 1px 0 rgba(0,0,0,0.2),0 0 0 2px #fff inset; 169 | border-radius: 2px; 170 | display: inline-block; 171 | margin: 0 .1em; 172 | text-shadow: 0 1px 0 #fff; 173 | line-height: 1.4; 174 | white-space: nowrap; 175 | } 176 | 177 | .bootstrap-tagsinput 178 | { 179 | background-color: #fff; 180 | border: 1px solid #ccc; 181 | box-shadow: inset 0 1px 1px rgba(0,0,0,0.075); 182 | display: block; 183 | color: #333; 184 | vertical-align: middle; 185 | border-radius: 0px; 186 | max-width: 100%; 187 | cursor: text; 188 | padding: 10px 16px; 189 | -webkit-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s; 190 | -o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s; 191 | transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s; 192 | } 193 | 194 | .bootstrap-tagsinput.focus 195 | { 196 | border-color: #66afe9; 197 | outline: 0; 198 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6); 199 | box-shadow: inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6); 200 | } 201 | 202 | .bootstrap-tagsinput input 203 | { 204 | border: none; 205 | box-shadow: none; 206 | outline: none; 207 | background-color: transparent; 208 | margin: 0; 209 | width: auto !important; 210 | max-width: inherit; 211 | } 212 | 213 | .bootstrap-tagsinput input:focus 214 | { 215 | border: none; 216 | box-shadow: none; 217 | } 218 | 219 | .bootstrap-tagsinput .tag 220 | { 221 | margin-right: 2px; 222 | } 223 | 224 | .bootstrap-tagsinput .tag [data-role="remove"] 225 | { 226 | margin-left: 8px; 227 | cursor: pointer; 228 | } 229 | 230 | .bootstrap-tagsinput .tag [data-role="remove"]:after 231 | { 232 | content: "x"; 233 | padding: 0px 2px; 234 | } 235 | 236 | .twitter-typeahead .tt-query, 237 | .twitter-typeahead .tt-hint 238 | { 239 | margin-bottom: 0; 240 | } 241 | 242 | .twitter-typeahead .tt-hint 243 | { 244 | display: none; 245 | } 246 | 247 | .tt-input 248 | { 249 | width: auto; 250 | } 251 | 252 | .tt-dropdown-menu 253 | { 254 | position: absolute; 255 | top: 100%; 256 | left: 0; 257 | z-index: 1000; 258 | display: none; 259 | float: left; 260 | min-width: 160px; 261 | padding: 5px 0; 262 | margin: 2px 0 0; 263 | list-style: none; 264 | background-color: #fff; 265 | border: 1px solid #ccc; 266 | border: 1px solid rgba(0, 0, 0, 0.15); 267 | border-radius: 0px; 268 | -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); 269 | box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); 270 | background-clip: padding-box; 271 | } 272 | 273 | .tt-suggestion > p 274 | { 275 | display: block; 276 | padding: 3px 20px; 277 | clear: both; 278 | font-weight: normal; 279 | line-height: 1.428571429; 280 | color: #333333; 281 | white-space: nowrap; 282 | cursor: pointer; 283 | margin: 0; 284 | } 285 | 286 | .tt-suggestion > p:hover, 287 | .tt-suggestion > p:focus, 288 | .tt-suggestion.tt-cursor p 289 | { 290 | color: #ffffff; 291 | text-decoration: none; 292 | outline: 0; 293 | background-color: #1a6ecc; 294 | } 295 | -------------------------------------------------------------------------------- /public/js/vendor/wow.min.js: -------------------------------------------------------------------------------- 1 | /*! WOW - v1.0.2 - 2014-09-24 2 | * Copyright (c) 2014 Matthieu Aussaguel; Licensed MIT */(function(){var a,b,c,d,e,f=function(a,b){return function(){return a.apply(b,arguments)}},g=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};b=function(){function a(){}return a.prototype.extend=function(a,b){var c,d;for(c in b)d=b[c],null==a[c]&&(a[c]=d);return a},a.prototype.isMobile=function(a){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(a)},a.prototype.addEvent=function(a,b,c){return null!=a.addEventListener?a.addEventListener(b,c,!1):null!=a.attachEvent?a.attachEvent("on"+b,c):a[b]=c},a.prototype.removeEvent=function(a,b,c){return null!=a.removeEventListener?a.removeEventListener(b,c,!1):null!=a.detachEvent?a.detachEvent("on"+b,c):delete a[b]},a.prototype.innerHeight=function(){return"innerHeight"in window?window.innerHeight:document.documentElement.clientHeight},a}(),c=this.WeakMap||this.MozWeakMap||(c=function(){function a(){this.keys=[],this.values=[]}return a.prototype.get=function(a){var b,c,d,e,f;for(f=this.keys,b=d=0,e=f.length;e>d;b=++d)if(c=f[b],c===a)return this.values[b]},a.prototype.set=function(a,b){var c,d,e,f,g;for(g=this.keys,c=e=0,f=g.length;f>e;c=++e)if(d=g[c],d===a)return void(this.values[c]=b);return this.keys.push(a),this.values.push(b)},a}()),a=this.MutationObserver||this.WebkitMutationObserver||this.MozMutationObserver||(a=function(){function a(){"undefined"!=typeof console&&null!==console&&console.warn("MutationObserver is not supported by your browser."),"undefined"!=typeof console&&null!==console&&console.warn("WOW.js cannot detect dom mutations, please call .sync() after loading new content.")}return a.notSupported=!0,a.prototype.observe=function(){},a}()),d=this.getComputedStyle||function(a){return this.getPropertyValue=function(b){var c;return"float"===b&&(b="styleFloat"),e.test(b)&&b.replace(e,function(a,b){return b.toUpperCase()}),(null!=(c=a.currentStyle)?c[b]:void 0)||null},this},e=/(\-([a-z]){1})/g,this.WOW=function(){function e(a){null==a&&(a={}),this.scrollCallback=f(this.scrollCallback,this),this.scrollHandler=f(this.scrollHandler,this),this.start=f(this.start,this),this.scrolled=!0,this.config=this.util().extend(a,this.defaults),this.animationNameCache=new c}return e.prototype.defaults={boxClass:"wow",animateClass:"animated",offset:0,mobile:!0,live:!0},e.prototype.init=function(){var a;return this.element=window.document.documentElement,"interactive"===(a=document.readyState)||"complete"===a?this.start():this.util().addEvent(document,"DOMContentLoaded",this.start),this.finished=[]},e.prototype.start=function(){var b,c,d,e;if(this.stopped=!1,this.boxes=function(){var a,c,d,e;for(d=this.element.querySelectorAll("."+this.config.boxClass),e=[],a=0,c=d.length;c>a;a++)b=d[a],e.push(b);return e}.call(this),this.all=function(){var a,c,d,e;for(d=this.boxes,e=[],a=0,c=d.length;c>a;a++)b=d[a],e.push(b);return e}.call(this),this.boxes.length)if(this.disabled())this.resetStyle();else{for(e=this.boxes,c=0,d=e.length;d>c;c++)b=e[c],this.applyStyle(b,!0);this.util().addEvent(window,"scroll",this.scrollHandler),this.util().addEvent(window,"resize",this.scrollHandler),this.interval=setInterval(this.scrollCallback,50)}return this.config.live?new a(function(a){return function(b){var c,d,e,f,g;for(g=[],e=0,f=b.length;f>e;e++)d=b[e],g.push(function(){var a,b,e,f;for(e=d.addedNodes||[],f=[],a=0,b=e.length;b>a;a++)c=e[a],f.push(this.doSync(c));return f}.call(a));return g}}(this)).observe(document.body,{childList:!0,subtree:!0}):void 0},e.prototype.stop=function(){return this.stopped=!0,this.util().removeEvent(window,"scroll",this.scrollHandler),this.util().removeEvent(window,"resize",this.scrollHandler),null!=this.interval?clearInterval(this.interval):void 0},e.prototype.sync=function(){return a.notSupported?this.doSync(this.element):void 0},e.prototype.doSync=function(a){var b,c,d,e,f;if(null==a&&(a=this.element),1===a.nodeType){for(a=a.parentNode||a,e=a.querySelectorAll("."+this.config.boxClass),f=[],c=0,d=e.length;d>c;c++)b=e[c],g.call(this.all,b)<0?(this.boxes.push(b),this.all.push(b),this.stopped||this.disabled()?this.resetStyle():this.applyStyle(b,!0),f.push(this.scrolled=!0)):f.push(void 0);return f}},e.prototype.show=function(a){return this.applyStyle(a),a.className=""+a.className+" "+this.config.animateClass},e.prototype.applyStyle=function(a,b){var c,d,e;return d=a.getAttribute("data-wow-duration"),c=a.getAttribute("data-wow-delay"),e=a.getAttribute("data-wow-iteration"),this.animate(function(f){return function(){return f.customStyle(a,b,d,c,e)}}(this))},e.prototype.animate=function(){return"requestAnimationFrame"in window?function(a){return window.requestAnimationFrame(a)}:function(a){return a()}}(),e.prototype.resetStyle=function(){var a,b,c,d,e;for(d=this.boxes,e=[],b=0,c=d.length;c>b;b++)a=d[b],e.push(a.style.visibility="visible");return e},e.prototype.customStyle=function(a,b,c,d,e){return b&&this.cacheAnimationName(a),a.style.visibility=b?"hidden":"visible",c&&this.vendorSet(a.style,{animationDuration:c}),d&&this.vendorSet(a.style,{animationDelay:d}),e&&this.vendorSet(a.style,{animationIterationCount:e}),this.vendorSet(a.style,{animationName:b?"none":this.cachedAnimationName(a)}),a},e.prototype.vendors=["moz","webkit"],e.prototype.vendorSet=function(a,b){var c,d,e,f;f=[];for(c in b)d=b[c],a[""+c]=d,f.push(function(){var b,f,g,h;for(g=this.vendors,h=[],b=0,f=g.length;f>b;b++)e=g[b],h.push(a[""+e+c.charAt(0).toUpperCase()+c.substr(1)]=d);return h}.call(this));return f},e.prototype.vendorCSS=function(a,b){var c,e,f,g,h,i;for(e=d(a),c=e.getPropertyCSSValue(b),i=this.vendors,g=0,h=i.length;h>g;g++)f=i[g],c=c||e.getPropertyCSSValue("-"+f+"-"+b);return c},e.prototype.animationName=function(a){var b;try{b=this.vendorCSS(a,"animation-name").cssText}catch(c){b=d(a).getPropertyValue("animation-name")}return"none"===b?"":b},e.prototype.cacheAnimationName=function(a){return this.animationNameCache.set(a,this.animationName(a))},e.prototype.cachedAnimationName=function(a){return this.animationNameCache.get(a)},e.prototype.scrollHandler=function(){return this.scrolled=!0},e.prototype.scrollCallback=function(){var a;return!this.scrolled||(this.scrolled=!1,this.boxes=function(){var b,c,d,e;for(d=this.boxes,e=[],b=0,c=d.length;c>b;b++)a=d[b],a&&(this.isVisible(a)?this.show(a):e.push(a));return e}.call(this),this.boxes.length||this.config.live)?void 0:this.stop()},e.prototype.offsetTop=function(a){for(var b;void 0===a.offsetTop;)a=a.parentNode;for(b=a.offsetTop;a=a.offsetParent;)b+=a.offsetTop;return b},e.prototype.isVisible=function(a){var b,c,d,e,f;return c=a.getAttribute("data-wow-offset")||this.config.offset,f=window.pageYOffset,e=f+Math.min(this.element.clientHeight,this.util().innerHeight())-c,d=this.offsetTop(a),b=d+a.clientHeight,e>=d&&b>=f},e.prototype.util=function(){return null!=this._util?this._util:this._util=new b},e.prototype.disabled=function(){return!this.config.mobile&&this.util().isMobile(navigator.userAgent)},e}()}).call(this); -------------------------------------------------------------------------------- /public/js/vendor/bootstrap-tagsinput.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * bootstrap-tagsinput v0.4.2 by Tim Schlechter 3 | * 4 | */ 5 | 6 | !function(a){"use strict";function b(b,c){this.itemsArray=[],this.$element=a(b),this.$element.hide(),this.isSelect="SELECT"===b.tagName,this.multiple=this.isSelect&&b.hasAttribute("multiple"),this.objectItems=c&&c.itemValue,this.placeholderText=b.hasAttribute("placeholder")?this.$element.attr("placeholder"):"",this.inputSize=Math.max(1,this.placeholderText.length),this.$container=a('
'),this.$input=a('').appendTo(this.$container),this.$element.after(this.$container);var d=(this.inputSize<3?3:this.inputSize)+"em";this.$input.get(0).style.cssText="width: "+d+" !important;",this.build(c)}function c(a,b){if("function"!=typeof a[b]){var c=a[b];a[b]=function(a){return a[c]}}}function d(a,b){if("function"!=typeof a[b]){var c=a[b];a[b]=function(){return c}}}function e(a){return a?i.text(a).html():""}function f(a){var b=0;if(document.selection){a.focus();var c=document.selection.createRange();c.moveStart("character",-a.value.length),b=c.text.length}else(a.selectionStart||"0"==a.selectionStart)&&(b=a.selectionStart);return b}function g(b,c){var d=!1;return a.each(c,function(a,c){if("number"==typeof c&&b.which===c)return d=!0,!1;if(b.which===c.which){var e=!c.hasOwnProperty("altKey")||b.altKey===c.altKey,f=!c.hasOwnProperty("shiftKey")||b.shiftKey===c.shiftKey,g=!c.hasOwnProperty("ctrlKey")||b.ctrlKey===c.ctrlKey;if(e&&f&&g)return d=!0,!1}}),d}var h={tagClass:function(){return"label label-info"},itemValue:function(a){return a?a.toString():a},itemText:function(a){return this.itemValue(a)},freeInput:!0,addOnBlur:!0,maxTags:void 0,maxChars:void 0,confirmKeys:[13,44],onTagExists:function(a,b){b.hide().fadeIn()},trimValue:!1,allowDuplicates:!1};b.prototype={constructor:b,add:function(b,c){var d=this;if(!(d.options.maxTags&&d.itemsArray.length>=d.options.maxTags||b!==!1&&!b)){if("string"==typeof b&&d.options.trimValue&&(b=a.trim(b)),"object"==typeof b&&!d.objectItems)throw"Can't add objects when itemValue option is not set";if(!b.toString().match(/^\s*$/)){if(d.isSelect&&!d.multiple&&d.itemsArray.length>0&&d.remove(d.itemsArray[0]),"string"==typeof b&&"INPUT"===this.$element[0].tagName){var f=b.split(",");if(f.length>1){for(var g=0;gd.options.maxInputLength)){var l=a.Event("beforeItemAdd",{item:b,cancel:!1});if(d.$element.trigger(l),!l.cancel){d.itemsArray.push(b);var m=a(''+e(i)+'');if(m.data("item",b),d.findInputWrapper().before(m),m.after(" "),d.isSelect&&!a('option[value="'+encodeURIComponent(h)+'"]',d.$element)[0]){var n=a("");n.data("item",b),n.attr("value",h),d.$element.append(n)}c||d.pushVal(),(d.options.maxTags===d.itemsArray.length||d.items().toString().length===d.options.maxInputLength)&&d.$container.addClass("bootstrap-tagsinput-max"),d.$element.trigger(a.Event("itemAdded",{item:b}))}}}else if(d.options.onTagExists){var o=a(".tag",d.$container).filter(function(){return a(this).data("item")===k});d.options.onTagExists(b,o)}}}},remove:function(b,c){var d=this;if(d.objectItems&&(b="object"==typeof b?a.grep(d.itemsArray,function(a){return d.options.itemValue(a)==d.options.itemValue(b)}):a.grep(d.itemsArray,function(a){return d.options.itemValue(a)==b}),b=b[b.length-1]),b){var e=a.Event("beforeItemRemove",{item:b,cancel:!1});if(d.$element.trigger(e),e.cancel)return;a(".tag",d.$container).filter(function(){return a(this).data("item")===b}).remove(),a("option",d.$element).filter(function(){return a(this).data("item")===b}).remove(),-1!==a.inArray(b,d.itemsArray)&&d.itemsArray.splice(a.inArray(b,d.itemsArray),1)}c||d.pushVal(),d.options.maxTags>d.itemsArray.length&&d.$container.removeClass("bootstrap-tagsinput-max"),d.$element.trigger(a.Event("itemRemoved",{item:b}))},removeAll:function(){var b=this;for(a(".tag",b.$container).remove(),a("option",b.$element).remove();b.itemsArray.length>0;)b.itemsArray.pop();b.pushVal()},refresh:function(){var b=this;a(".tag",b.$container).each(function(){var c=a(this),d=c.data("item"),f=b.options.itemValue(d),g=b.options.itemText(d),h=b.options.tagClass(d);if(c.attr("class",null),c.addClass("tag "+e(h)),c.contents().filter(function(){return 3==this.nodeType})[0].nodeValue=e(g),b.isSelect){var i=a("option",b.$element).filter(function(){return a(this).data("item")===d});i.attr("value",f)}})},items:function(){return this.itemsArray},pushVal:function(){var b=this,c=a.map(b.items(),function(a){return b.options.itemValue(a).toString()});b.$element.val(c,!0).trigger("change")},build:function(b){var e=this;if(e.options=a.extend({},h,b),e.objectItems&&(e.options.freeInput=!1),c(e.options,"itemValue"),c(e.options,"itemText"),d(e.options,"tagClass"),e.options.typeahead){var i=e.options.typeahead||{};d(i,"source"),e.$input.typeahead(a.extend({},i,{source:function(b,c){function d(a){for(var b=[],d=0;d$1")}}))}if(e.options.typeaheadjs){var j=e.options.typeaheadjs||{};e.$input.typeahead(null,j).on("typeahead:selected",a.proxy(function(a,b){e.add(j.valueKey?b[j.valueKey]:b),e.$input.typeahead("val","")},e))}e.$container.on("click",a.proxy(function(){e.$element.attr("disabled")||e.$input.removeAttr("disabled"),e.$input.focus()},e)),e.options.addOnBlur&&e.options.freeInput&&e.$input.on("focusout",a.proxy(function(){0===a(".typeahead, .twitter-typeahead",e.$container).length&&(e.add(e.$input.val()),e.$input.val(""))},e)),e.$container.on("keydown","input",a.proxy(function(b){var c=a(b.target),d=e.findInputWrapper();if(e.$element.attr("disabled"))return void e.$input.attr("disabled","disabled");switch(b.which){case 8:if(0===f(c[0])){var g=d.prev();g&&e.remove(g.data("item"))}break;case 46:if(0===f(c[0])){var h=d.next();h&&e.remove(h.data("item"))}break;case 37:var i=d.prev();0===c.val().length&&i[0]&&(i.before(d),c.focus());break;case 39:var j=d.next();0===c.val().length&&j[0]&&(j.after(d),c.focus())}{var k=c.val().length;Math.ceil(k/5)}c.attr("size",Math.max(this.inputSize,c.val().length))},e)),e.$container.on("keypress","input",a.proxy(function(b){var c=a(b.target);if(e.$element.attr("disabled"))return void e.$input.attr("disabled","disabled");var d=c.val(),f=e.options.maxChars&&d.length>=e.options.maxChars;e.options.freeInput&&(g(b,e.options.confirmKeys)||f)&&(e.add(f?d.substr(0,e.options.maxChars):d),c.val(""),b.preventDefault());{var h=c.val().length;Math.ceil(h/5)}c.attr("size",Math.max(this.inputSize,c.val().length))},e)),e.$container.on("click","[data-role=remove]",a.proxy(function(b){e.$element.attr("disabled")||e.remove(a(b.target).closest(".tag").data("item"))},e)),e.options.itemValue===h.itemValue&&("INPUT"===e.$element[0].tagName?e.add(e.$element.val()):a("option",e.$element).each(function(){e.add(a(this).attr("value"),!0)}))},destroy:function(){var a=this;a.$container.off("keypress","input"),a.$container.off("click","[role=remove]"),a.$container.remove(),a.$element.removeData("tagsinput"),a.$element.show()},focus:function(){this.$input.focus()},input:function(){return this.$input},findInputWrapper:function(){for(var b=this.$input[0],c=this.$container[0];b&&b.parentNode!==c;)b=b.parentNode;return a(b)}},a.fn.tagsinput=function(c,d){var e=[];return this.each(function(){var f=a(this).data("tagsinput");if(f)if(c||d){if(void 0!==f[c]){var g=f[c](d);void 0!==g&&e.push(g)}}else e.push(f);else f=new b(this,c),a(this).data("tagsinput",f),e.push(f),"SELECT"===this.tagName&&a("option",a(this)).attr("selected","selected"),a(this).val(a(this).val())}),"string"==typeof c?e.length>1?e:e[0]:e},a.fn.tagsinput.Constructor=b;var i=a("
");a(function(){a("input[data-role=tagsinput], select[multiple][data-role=tagsinput]").tagsinput()})}(window.jQuery); 7 | //# sourceMappingURL=bootstrap-tagsinput.min.js.map -------------------------------------------------------------------------------- /app/config/app.php: -------------------------------------------------------------------------------- 1 | false, 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Application URL 21 | |-------------------------------------------------------------------------- 22 | | 23 | | This URL is used by the console to properly generate URLs when using 24 | | the Artisan command line tool. You should set this to the root of 25 | | your application so that it is used when running Artisan tasks. 26 | | 27 | */ 28 | 29 | 'url' => 'http://vimrcfu.com', 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Application Timezone 34 | |-------------------------------------------------------------------------- 35 | | 36 | | Here you may specify the default timezone for your application, which 37 | | will be used by the PHP date and date-time functions. We have gone 38 | | ahead and set this to a sensible default for you out of the box. 39 | | 40 | */ 41 | 42 | 'timezone' => 'UTC', 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Application Locale Configuration 47 | |-------------------------------------------------------------------------- 48 | | 49 | | The application locale determines the default locale that will be used 50 | | by the translation service provider. You are free to set this value 51 | | to any of the locales which will be supported by the application. 52 | | 53 | */ 54 | 55 | 'locale' => 'en', 56 | 57 | /* 58 | |-------------------------------------------------------------------------- 59 | | Application Fallback Locale 60 | |-------------------------------------------------------------------------- 61 | | 62 | | The fallback locale determines the locale to use when the current one 63 | | is not available. You may change the value to correspond to any of 64 | | the language folders that are provided through your application. 65 | | 66 | */ 67 | 68 | 'fallback_locale' => 'en', 69 | 70 | /* 71 | |-------------------------------------------------------------------------- 72 | | Encryption Key 73 | |-------------------------------------------------------------------------- 74 | | 75 | | This key is used by the Illuminate encrypter service and should be set 76 | | to a random, 32 character string, otherwise these encrypted strings 77 | | will not be safe. Please do this before deploying an application! 78 | | 79 | */ 80 | 81 | 'key' => getenv('APP_KEY'), 82 | 83 | 'cipher' => MCRYPT_RIJNDAEL_128, 84 | 85 | /* 86 | |-------------------------------------------------------------------------- 87 | | Autoloaded Service Providers 88 | |-------------------------------------------------------------------------- 89 | | 90 | | The service providers listed here will be automatically loaded on the 91 | | request to your application. Feel free to add your own services to 92 | | this array to grant expanded functionality to your applications. 93 | | 94 | */ 95 | 96 | 'providers' => array( 97 | 98 | 'Illuminate\Foundation\Providers\ArtisanServiceProvider', 99 | 'Illuminate\Auth\AuthServiceProvider', 100 | 'Illuminate\Cache\CacheServiceProvider', 101 | 'Illuminate\Session\CommandsServiceProvider', 102 | 'Illuminate\Foundation\Providers\ConsoleSupportServiceProvider', 103 | 'Illuminate\Routing\ControllerServiceProvider', 104 | 'Illuminate\Cookie\CookieServiceProvider', 105 | 'Illuminate\Database\DatabaseServiceProvider', 106 | 'Illuminate\Encryption\EncryptionServiceProvider', 107 | 'Illuminate\Filesystem\FilesystemServiceProvider', 108 | 'Illuminate\Hashing\HashServiceProvider', 109 | 'Illuminate\Html\HtmlServiceProvider', 110 | 'Illuminate\Log\LogServiceProvider', 111 | 'Illuminate\Mail\MailServiceProvider', 112 | 'Illuminate\Database\MigrationServiceProvider', 113 | 'Illuminate\Pagination\PaginationServiceProvider', 114 | 'Illuminate\Queue\QueueServiceProvider', 115 | 'Illuminate\Redis\RedisServiceProvider', 116 | 'Illuminate\Remote\RemoteServiceProvider', 117 | 'Illuminate\Auth\Reminders\ReminderServiceProvider', 118 | 'Illuminate\Database\SeedServiceProvider', 119 | 'Illuminate\Session\SessionServiceProvider', 120 | 'Illuminate\Translation\TranslationServiceProvider', 121 | 'Illuminate\Validation\ValidationServiceProvider', 122 | 'Illuminate\View\ViewServiceProvider', 123 | 'Illuminate\Workbench\WorkbenchServiceProvider', 124 | 'Artdarek\OAuth\OAuthServiceProvider', 125 | 'Vimrcfu\Providers\CoreServiceProvider', 126 | 'Vimrcfu\Providers\PersistenceServiceProvider', 127 | 128 | ), 129 | 130 | /* 131 | |-------------------------------------------------------------------------- 132 | | Service Provider Manifest 133 | |-------------------------------------------------------------------------- 134 | | 135 | | The service provider manifest is used by Laravel to lazy load service 136 | | providers which are not needed for each request, as well to keep a 137 | | list of all of the services. Here, you may set its storage spot. 138 | | 139 | */ 140 | 141 | 'manifest' => storage_path().'/meta', 142 | 143 | /* 144 | |-------------------------------------------------------------------------- 145 | | Class Aliases 146 | |-------------------------------------------------------------------------- 147 | | 148 | | This array of class aliases will be registered when this application 149 | | is started. However, feel free to register as many as you wish as 150 | | the aliases are "lazy" loaded so they don't hinder performance. 151 | | 152 | */ 153 | 154 | 'aliases' => array( 155 | 156 | 'App' => 'Illuminate\Support\Facades\App', 157 | 'Artisan' => 'Illuminate\Support\Facades\Artisan', 158 | 'Auth' => 'Illuminate\Support\Facades\Auth', 159 | 'Blade' => 'Illuminate\Support\Facades\Blade', 160 | 'Cache' => 'Illuminate\Support\Facades\Cache', 161 | 'ClassLoader' => 'Illuminate\Support\ClassLoader', 162 | 'Config' => 'Illuminate\Support\Facades\Config', 163 | 'Controller' => 'Illuminate\Routing\Controller', 164 | 'Cookie' => 'Illuminate\Support\Facades\Cookie', 165 | 'Crypt' => 'Illuminate\Support\Facades\Crypt', 166 | 'DB' => 'Illuminate\Support\Facades\DB', 167 | 'Eloquent' => 'Illuminate\Database\Eloquent\Model', 168 | 'Event' => 'Illuminate\Support\Facades\Event', 169 | 'File' => 'Illuminate\Support\Facades\File', 170 | 'Form' => 'Illuminate\Support\Facades\Form', 171 | 'Hash' => 'Illuminate\Support\Facades\Hash', 172 | 'HTML' => 'Illuminate\Support\Facades\HTML', 173 | 'Input' => 'Illuminate\Support\Facades\Input', 174 | 'Lang' => 'Illuminate\Support\Facades\Lang', 175 | 'Log' => 'Illuminate\Support\Facades\Log', 176 | 'Mail' => 'Illuminate\Support\Facades\Mail', 177 | 'Paginator' => 'Illuminate\Support\Facades\Paginator', 178 | 'Password' => 'Illuminate\Support\Facades\Password', 179 | 'Queue' => 'Illuminate\Support\Facades\Queue', 180 | 'Redirect' => 'Illuminate\Support\Facades\Redirect', 181 | 'Redis' => 'Illuminate\Support\Facades\Redis', 182 | 'Request' => 'Illuminate\Support\Facades\Request', 183 | 'Response' => 'Illuminate\Support\Facades\Response', 184 | 'Route' => 'Illuminate\Support\Facades\Route', 185 | 'Schema' => 'Illuminate\Support\Facades\Schema', 186 | 'Seeder' => 'Illuminate\Database\Seeder', 187 | 'Session' => 'Illuminate\Support\Facades\Session', 188 | 'SoftDeletingTrait' => 'Illuminate\Database\Eloquent\SoftDeletingTrait', 189 | 'SSH' => 'Illuminate\Support\Facades\SSH', 190 | 'Str' => 'Illuminate\Support\Str', 191 | 'URL' => 'Illuminate\Support\Facades\URL', 192 | 'Validator' => 'Illuminate\Support\Facades\Validator', 193 | 'View' => 'Illuminate\Support\Facades\View', 194 | 'OAuth' => 'Artdarek\OAuth\Facade\OAuth', 195 | 'Text' => 'Vimrcfu\Facades\TextFacade', 196 | 197 | ), 198 | 199 | ); 200 | -------------------------------------------------------------------------------- /public/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.1.1 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | .btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn:active,.btn.active{background-image:none}.btn-default{background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #fff;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-color:#357ebd}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:linear-gradient(to bottom,#222 0,#282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0)}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} --------------------------------------------------------------------------------