├── .babelrc
├── .dockerignore
├── .editorconfig
├── .env.example
├── .gitattributes
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── app
├── Article.php
├── Category.php
├── Comment.php
├── Console
│ ├── Commands
│ │ ├── BlogInstall.php
│ │ └── CreateAdmin.php
│ └── Kernel.php
├── Discussion.php
├── Exceptions
│ ├── Handler.php
│ └── UploadException.php
├── Follower.php
├── Helpers.php
├── Http
│ ├── Controllers
│ │ ├── Api
│ │ │ ├── ApiController.php
│ │ │ ├── ArticleController.php
│ │ │ ├── CategoryController.php
│ │ │ ├── CommentController.php
│ │ │ ├── DiscussionController.php
│ │ │ ├── HomeController.php
│ │ │ ├── LinkController.php
│ │ │ ├── MeController.php
│ │ │ ├── PermissionsController.php
│ │ │ ├── RoleController.php
│ │ │ ├── SystemController.php
│ │ │ ├── TagController.php
│ │ │ ├── UploadController.php
│ │ │ ├── UserController.php
│ │ │ └── VisitorController.php
│ │ ├── ArticleController.php
│ │ ├── Auth
│ │ │ ├── AuthController.php
│ │ │ ├── ForgotPasswordController.php
│ │ │ ├── LoginController.php
│ │ │ ├── RegisterController.php
│ │ │ └── ResetPasswordController.php
│ │ ├── CategoryController.php
│ │ ├── Controller.php
│ │ ├── DiscussionController.php
│ │ ├── HomeController.php
│ │ ├── LinkController.php
│ │ ├── SettingController.php
│ │ ├── TagController.php
│ │ └── UserController.php
│ ├── Kernel.php
│ ├── Middleware
│ │ ├── Authenticate.php
│ │ ├── CheckForMaintenanceMode.php
│ │ ├── EncryptCookies.php
│ │ ├── MustBeAdmin.php
│ │ ├── PermissionMiddleware.php
│ │ ├── RedirectIfAuthenticated.php
│ │ ├── TrimStrings.php
│ │ ├── TrustProxies.php
│ │ └── VerifyCsrfToken.php
│ └── Requests
│ │ ├── ArticleRequest.php
│ │ ├── CategoryRequest.php
│ │ ├── CommentRequest.php
│ │ ├── DiscussionRequest.php
│ │ ├── ImageRequest.php
│ │ ├── LinkRequest.php
│ │ ├── TagRequest.php
│ │ └── UserRequest.php
├── Link.php
├── Model.php
├── ModelFilters
│ ├── ArticleFilter.php
│ ├── CategoryFilter.php
│ ├── CommentFilter.php
│ ├── DiscussionFilter.php
│ ├── LinkFilter.php
│ ├── RoleFilter.php
│ ├── TagFilter.php
│ ├── UserFilter.php
│ └── VisitorFilter.php
├── Notifications
│ ├── FollowedUser.php
│ ├── GotVote.php
│ ├── MentionedUser.php
│ └── ReceivedComment.php
├── Policies
│ ├── ArticlePolicy.php
│ ├── CommentPolicy.php
│ ├── DiscussionPolicy.php
│ ├── Policy.php
│ └── UserPolicy.php
├── Providers
│ ├── AppServiceProvider.php
│ ├── AuthServiceProvider.php
│ ├── BroadcastServiceProvider.php
│ ├── EventServiceProvider.php
│ └── RouteServiceProvider.php
├── Scopes
│ ├── DraftScope.php
│ └── StatusScope.php
├── Support
│ ├── Response.php
│ └── Transform.php
├── Tag.php
├── Tools
│ ├── FileManager
│ │ ├── BaseManager.php
│ │ └── UpyunManager.php
│ ├── IP.php
│ ├── Markdowner.php
│ └── Mention.php
├── Traits
│ ├── BelongsToUser.php
│ ├── FollowTrait.php
│ ├── HasComments.php
│ └── HasTags.php
├── Transformers
│ ├── ArticleTransformer.php
│ ├── CategoryTransformer.php
│ ├── CommentTransformer.php
│ ├── DiscussionTransformer.php
│ ├── EmptyTransformer.php
│ ├── LinkTransformer.php
│ ├── PermissionTransformer.php
│ ├── RoleTransformer.php
│ ├── TagTransformer.php
│ ├── UserTransformer.php
│ └── VisitorTransformer.php
├── User.php
└── Visitor.php
├── artisan
├── bootstrap
├── app.php
└── cache
│ └── .gitignore
├── composer.json
├── composer.lock
├── config
├── app.php
├── auth.php
├── blog.php
├── broadcasting.php
├── cache.php
├── compile.php
├── cors.php
├── database.php
├── eloquentfilter.php
├── filesystems.php
├── hashing.php
├── image.php
├── logging.php
├── mail.php
├── permission.php
├── queue.php
├── services.php
├── session.php
├── view.php
└── vote.php
├── database
├── .gitignore
├── factories
│ └── ModelFactory.php
├── migrations
│ ├── .gitkeep
│ ├── 2014_10_12_000000_create_users_table.php
│ ├── 2014_10_12_100000_create_password_resets_table.php
│ ├── 2016_09_02_065857_create_articles_table.php
│ ├── 2016_09_02_065920_create_tags_table.php
│ ├── 2016_09_02_065952_create_visitors_table.php
│ ├── 2016_09_02_070119_create_categories_table.php
│ ├── 2016_09_02_070132_create_discussions_table.php
│ ├── 2016_09_02_070151_create_comments_table.php
│ ├── 2016_09_13_022056_create_links_table.php
│ ├── 2016_11_11_163610_create_taggables_table.php
│ ├── 2016_12_11_153312_create_followers_table.php
│ ├── 2016_12_12_171655_create_notifications_table.php
│ ├── 2016_12_12_205419_create_failed_jobs_table.php
│ └── 2018_05_22_091255_create_permission_tables.php
└── seeds
│ ├── .gitkeep
│ ├── ArticlesTableSeeder.php
│ ├── CategoriesTableSeeder.php
│ ├── CommentsTableSeeder.php
│ ├── DatabaseSeeder.php
│ ├── DiscussionsTableSeeder.php
│ ├── LinksTableSeeder.php
│ ├── PermissionTableSeeder.php
│ ├── TagsTableSeeder.php
│ ├── UsersTableSeeder.php
│ └── VisitorsTableSeeder.php
├── entrypoint.sh
├── package.json
├── phpunit.xml
├── public
├── .gitignore
├── .htaccess
├── favicon.ico
├── images
│ ├── default.png
│ └── favicon.ico
├── index.php
├── robots.txt
└── web.config
├── resources
├── js
│ ├── App.vue
│ ├── app.js
│ ├── bootstrap.js
│ ├── config
│ │ ├── base.js
│ │ ├── helper.js
│ │ └── toastr.js
│ ├── dashboard
│ │ ├── Main.vue
│ │ ├── components
│ │ │ ├── CustomAction.vue
│ │ │ ├── Form.vue
│ │ │ ├── Modal.vue
│ │ │ ├── Table.vue
│ │ │ ├── TablePagination.vue
│ │ │ ├── TablePaginationMixin.vue
│ │ │ └── particals
│ │ │ │ ├── FooterBar.vue
│ │ │ │ ├── Navbar.vue
│ │ │ │ └── Sidebar.vue
│ │ ├── config
│ │ │ └── menu.js
│ │ ├── index.js
│ │ ├── modules
│ │ │ ├── article
│ │ │ │ ├── Article.vue
│ │ │ │ ├── Create.vue
│ │ │ │ ├── Edit.vue
│ │ │ │ ├── Form.vue
│ │ │ │ ├── FormMixin.vue
│ │ │ │ ├── index.js
│ │ │ │ └── routes.js
│ │ │ ├── category
│ │ │ │ ├── Category.vue
│ │ │ │ ├── Create.vue
│ │ │ │ ├── Edit.vue
│ │ │ │ ├── Form.vue
│ │ │ │ ├── index.js
│ │ │ │ └── routes.js
│ │ │ ├── comment
│ │ │ │ ├── Comment.vue
│ │ │ │ ├── Edit.vue
│ │ │ │ ├── index.js
│ │ │ │ └── routes.js
│ │ │ ├── discussion
│ │ │ │ ├── Create.vue
│ │ │ │ ├── Discussion.vue
│ │ │ │ ├── Edit.vue
│ │ │ │ ├── Form.vue
│ │ │ │ ├── index.js
│ │ │ │ └── routes.js
│ │ │ ├── file
│ │ │ │ ├── File.vue
│ │ │ │ ├── index.js
│ │ │ │ └── routes.js
│ │ │ ├── home
│ │ │ │ ├── Home.vue
│ │ │ │ ├── index.js
│ │ │ │ └── routes.js
│ │ │ ├── link
│ │ │ │ ├── Create.vue
│ │ │ │ ├── Edit.vue
│ │ │ │ ├── Form.vue
│ │ │ │ ├── Link.vue
│ │ │ │ ├── index.js
│ │ │ │ └── routes.js
│ │ │ ├── role
│ │ │ │ ├── Create.vue
│ │ │ │ ├── Edit.vue
│ │ │ │ ├── Form.vue
│ │ │ │ ├── Permission.vue
│ │ │ │ ├── Role.vue
│ │ │ │ ├── index.js
│ │ │ │ └── routes.js
│ │ │ ├── system
│ │ │ │ ├── System.vue
│ │ │ │ ├── index.js
│ │ │ │ └── routes.js
│ │ │ ├── tag
│ │ │ │ ├── Create.vue
│ │ │ │ ├── Edit.vue
│ │ │ │ ├── Form.vue
│ │ │ │ ├── Tag.vue
│ │ │ │ ├── index.js
│ │ │ │ └── routes.js
│ │ │ ├── user
│ │ │ │ ├── Create.vue
│ │ │ │ ├── Edit.vue
│ │ │ │ ├── Form.vue
│ │ │ │ ├── User.vue
│ │ │ │ ├── index.js
│ │ │ │ └── routes.js
│ │ │ └── visitor
│ │ │ │ ├── Visitor.vue
│ │ │ │ ├── index.js
│ │ │ │ └── routes.js
│ │ ├── routes.js
│ │ └── runtime
│ │ │ ├── constants
│ │ │ └── permission.js
│ │ │ ├── mixins
│ │ │ └── index.js
│ │ │ └── utils
│ │ │ ├── index.js
│ │ │ └── misc.js
│ ├── home.js
│ ├── home
│ │ └── components
│ │ │ ├── AvatarUpload.vue
│ │ │ ├── Chartjs.vue
│ │ │ ├── Comment.vue
│ │ │ ├── Cropper.vue
│ │ │ ├── Parse.vue
│ │ │ ├── Textarea.vue
│ │ │ ├── VoteButton.vue
│ │ │ └── passport
│ │ │ ├── AuthorizedClients.vue
│ │ │ ├── Clients.vue
│ │ │ └── PersonalAccessTokens.vue
│ ├── lang
│ │ ├── en
│ │ │ ├── form.js
│ │ │ ├── index.js
│ │ │ ├── page.js
│ │ │ ├── permission.js
│ │ │ ├── sidebar.js
│ │ │ └── table.js
│ │ ├── es
│ │ │ ├── form.js
│ │ │ ├── index.js
│ │ │ ├── page.js
│ │ │ ├── permission.js
│ │ │ ├── sidebar.js
│ │ │ └── table.js
│ │ ├── index.js
│ │ ├── ru
│ │ │ ├── form.js
│ │ │ ├── index.js
│ │ │ ├── page.js
│ │ │ ├── permission.js
│ │ │ ├── sidebar.js
│ │ │ └── table.js
│ │ └── zh_cn
│ │ │ ├── form.js
│ │ │ ├── index.js
│ │ │ ├── page.js
│ │ │ ├── permission.js
│ │ │ ├── sidebar.js
│ │ │ └── table.js
│ ├── plugins
│ │ └── http
│ │ │ └── index.js
│ ├── router
│ │ ├── beforeEach.js
│ │ └── index.js
│ ├── vendor
│ │ ├── github_emoji.js
│ │ ├── highlight.min.js
│ │ └── select2.min.js
│ └── vuex
│ │ ├── actions.js
│ │ ├── mutations.js
│ │ └── store.js
├── lang
│ ├── en
│ │ ├── auth.php
│ │ ├── blog.php
│ │ ├── pagination.php
│ │ ├── passwords.php
│ │ ├── permissions.php
│ │ └── validation.php
│ ├── es
│ │ ├── auth.php
│ │ ├── blog.php
│ │ ├── pagination.php
│ │ ├── passwords.php
│ │ ├── permissions.php
│ │ └── validation.php
│ ├── ru
│ │ ├── auth.php
│ │ ├── blog.php
│ │ ├── pagination.php
│ │ ├── passwords.php
│ │ ├── permissions.php
│ │ └── validation.php
│ └── zh_cn
│ │ ├── auth.php
│ │ ├── blog.php
│ │ ├── pagination.php
│ │ ├── passwords.php
│ │ ├── permissions.php
│ │ └── validation.php
├── sass
│ ├── _box.scss
│ ├── _comment.scss
│ ├── _form.scss
│ ├── _markdown.scss
│ ├── _navbar.scss
│ ├── _pagination.scss
│ ├── _styles.scss
│ ├── _toastr.scss
│ ├── _togglebutton.scss
│ ├── _variables.scss
│ ├── app.scss
│ ├── home.scss
│ ├── public.scss
│ ├── themes
│ │ ├── default-theme.scss
│ │ └── gray-theme.scss
│ └── vendor
│ │ ├── highlight.min.css
│ │ ├── select2.min.css
│ │ ├── simplemde.min.css
│ │ └── toastr.min.css
└── views
│ ├── article
│ ├── index.blade.php
│ └── show.blade.php
│ ├── auth
│ ├── github_register.blade.php
│ ├── login.blade.php
│ ├── passwords
│ │ ├── email.blade.php
│ │ └── reset.blade.php
│ └── register.blade.php
│ ├── category
│ ├── index.blade.php
│ └── show.blade.php
│ ├── dashboard
│ └── index.blade.php
│ ├── discussion
│ ├── create.blade.php
│ ├── edit.blade.php
│ ├── index.blade.php
│ └── show.blade.php
│ ├── errors
│ ├── 403.blade.php
│ ├── 404.blade.php
│ └── 503.blade.php
│ ├── layouts
│ └── app.blade.php
│ ├── link
│ └── index.blade.php
│ ├── mail
│ ├── followed
│ │ └── user.blade.php
│ ├── mention
│ │ └── user.blade.php
│ └── receive
│ │ └── comment.blade.php
│ ├── notifications
│ ├── followed-user.blade.php
│ ├── got-vote.blade.php
│ ├── mentioned-user.blade.php
│ └── received-comment.blade.php
│ ├── pagination
│ └── default.blade.php
│ ├── particals
│ ├── footer.blade.php
│ ├── jumbotron.blade.php
│ └── navbar.blade.php
│ ├── search.blade.php
│ ├── setting
│ ├── binding.blade.php
│ ├── index.blade.php
│ ├── notification.blade.php
│ └── particals
│ │ └── sidebar.blade.php
│ ├── tag
│ ├── index.blade.php
│ └── show.blade.php
│ ├── user
│ ├── comments.blade.php
│ ├── discussions.blade.php
│ ├── following.blade.php
│ ├── index.blade.php
│ ├── notifications.blade.php
│ ├── particals
│ │ ├── comments.blade.php
│ │ ├── discussions.blade.php
│ │ └── info.blade.php
│ └── profile.blade.php
│ ├── vendor
│ └── notifications
│ │ ├── email-plain.blade.php
│ │ └── email.blade.php
│ └── widgets
│ └── article.blade.php
├── routes
├── api.php
├── channels.php
├── console.php
└── web.php
├── server.php
├── storage
├── app
│ ├── .gitignore
│ └── public
│ │ └── .gitignore
├── framework
│ ├── .gitignore
│ ├── cache
│ │ ├── .gitignore
│ │ └── data
│ │ │ └── .gitignore
│ ├── sessions
│ │ └── .gitignore
│ └── views
│ │ └── .gitignore
└── logs
│ └── .gitignore
├── tests
├── CreatesApplication.php
├── Feature
│ ├── Api
│ │ ├── ArticleApiTest.php
│ │ └── UserApiTest.php
│ └── ExampleTest.php
├── TestCase.php
└── Unit
│ └── ExampleTest.php
├── webpack.mix.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [["@babel/preset-env", { "modules": false }]],
3 | "plugins": ["@babel/plugin-syntax-dynamic-import"]
4 | }
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.dockerignore
3 | **/.env
4 | **/.git
5 | **/.gitignore
6 | **/.project
7 | **/.settings
8 | **/.toolstarget
9 | **/.vs
10 | **/.vscode
11 | **/*.*proj.user
12 | **/*.dbmdl
13 | **/*.jfm
14 | **/charts
15 | **/docker-compose*
16 | **/Dockerfile*
17 | **/node_modules
18 | **/npm-debug.log
19 | **/obj
20 | **/secrets.dev.yaml
21 | **/values.dev.yaml
22 | README.md
23 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 4
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = false
10 |
11 | [*.{vue,js,scss}]
12 | charset = utf-8
13 | indent_style = space
14 | indent_size = 2
15 | end_of_line = lf
16 | insert_final_newline = true
17 | trim_trailing_whitespace = true
18 |
19 | [*.md]
20 | trim_trailing_whitespace = false
21 |
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | APP_NAME=PJ-Blog
2 | APP_ENV=local
3 | APP_KEY=
4 | APP_DEBUG=true
5 | APP_URL=http://localhost
6 | APP_SUPER_ADMIN=1
7 |
8 | LOG_CHANNEL=stack
9 |
10 | DB_CONNECTION=mysql
11 | DB_HOST=127.0.0.1
12 | DB_PORT=3306
13 | DB_DATABASE=laravel
14 | DB_USERNAME=root
15 | DB_PASSWORD=
16 |
17 | BROADCAST_DRIVER=log
18 | CACHE_DRIVER=file
19 | QUEUE_CONNECTION=sync
20 | SESSION_DRIVER=file
21 | SESSION_LIFETIME=120
22 |
23 | REDIS_HOST=127.0.0.1
24 | REDIS_PASSWORD=null
25 | REDIS_PORT=6379
26 |
27 | MAIL_MAILER=smtp
28 | MAIL_HOST=mailpit
29 | MAIL_PORT=1025
30 | MAIL_USERNAME=null
31 | MAIL_PASSWORD=null
32 | MAIL_ENCRYPTION=null
33 | MAIL_FROM_ADDRESS="hello@example.com"
34 | MAIL_FROM_NAME="${APP_NAME}"
35 |
36 | ADMIN_NAME=
37 | ADMIN_EMAIL=
38 | ADMIN_PASSWORD=
39 |
40 | AWS_ACCESS_KEY_ID=
41 | AWS_SECRET_ACCESS_KEY=
42 | AWS_DEFAULT_REGION=us-east-1
43 | AWS_BUCKET=
44 |
45 | PUSHER_APP_ID=
46 | PUSHER_APP_KEY=
47 | PUSHER_APP_SECRET=
48 | PUSHER_APP_CLUSTER=mt1
49 |
50 | MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
51 | MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
52 |
53 | GITHUB_CLIENT_ID=
54 | GITHUB_CLIENT_SECRET=
55 | GITHUB_REDIRECT=
56 |
57 | YOUDAO_APP_KEY=
58 | YOUDAO_APP_SECRET=
59 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | *.css linguist-vendored
3 | *.scss linguist-vendored
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /public/storage
3 | /vendor
4 | /.idea
5 | Homestead.json
6 | Homestead.yaml
7 | .env
8 | /public/css
9 | /public/js
10 | /public/fonts
11 | /public/mix-manifest.json
12 | npm-debug.log
13 | .phpstorm.meta.php
14 | _ide_helper.php
15 | /storage/oauth-private.key
16 | /storage/oauth-public.key
17 | /package-lock.json
18 | .vscode/*
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM php:7.4-fpm
2 |
3 | COPY . /usr/src/blog
4 | WORKDIR /usr/src/blog
5 |
6 | # install tools
7 | RUN apt-get -y update
8 | RUN apt-get -y install git
9 | RUN apt-get -y install vim
10 | RUN apt-get install zip unzip
11 | RUN apt-get -y install libxml2-dev
12 |
13 | # install PHP extenstions
14 | RUN docker-php-ext-install pdo
15 | RUN docker-php-ext-install pdo_mysql
16 |
17 | RUN docker-php-ext-install tokenizer
18 | RUN docker-php-ext-install xml
19 |
20 | #node js
21 | RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash -
22 | RUN apt-get install -y nodejs
23 |
24 | # install composer
25 | COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
26 |
27 | # install app
28 | RUN composer install -vvv
29 | RUN npm install
30 | RUN composer update
31 | RUN npm run dev
32 |
33 | COPY entrypoint.sh /entrypoint.sh
34 |
35 | CMD ["/entrypoint.sh"]
36 |
37 | EXPOSE 8000
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Jiajian Chan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/app/Category.php:
--------------------------------------------------------------------------------
1 | hasMany(Article::Class);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/Comment.php:
--------------------------------------------------------------------------------
1 | morphTo();
43 | }
44 |
45 | /**
46 | * Set the content Attribute.
47 | *
48 | * @param $value
49 | */
50 | public function setContentAttribute($value)
51 | {
52 | $data = [
53 | 'raw' => $value,
54 | 'html' => (new Markdowner)->convertMarkdownToHtml($value)
55 | ];
56 |
57 | $this->attributes['content'] = json_encode($data);
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/app/Console/Commands/BlogInstall.php:
--------------------------------------------------------------------------------
1 | execShellWithPrettyPrint('php artisan key:generate');
39 | $this->execShellWithPrettyPrint('php artisan migrate --seed');
40 | $this->execShellWithPrettyPrint('php artisan passport:install');
41 | $this->execShellWithPrettyPrint('php artisan storage:link');
42 | }
43 |
44 | /**
45 | * Exec shell with pretty print.
46 | *
47 | * @param string $command
48 | * @return mixed
49 | */
50 | public function execShellWithPrettyPrint($command)
51 | {
52 | $this->info('---');
53 | $this->info($command);
54 | $output = shell_exec($command);
55 | $this->info($output);
56 | $this->info('---');
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/app/Console/Kernel.php:
--------------------------------------------------------------------------------
1 | command('inspire')
29 | // ->hourly();
30 | }
31 |
32 | /**
33 | * Register the Closure based commands for the application.
34 | *
35 | * @return void
36 | */
37 | protected function commands()
38 | {
39 | require base_path('routes/console.php');
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/Exceptions/UploadException.php:
--------------------------------------------------------------------------------
1 | response = new Response(response(), new Transform($manager));
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Api/HomeController.php:
--------------------------------------------------------------------------------
1 | count();
15 | $visitors = Visitor::query()->sum('clicks');
16 | $articles = Article::query()->count();
17 | $comments = Comment::query()->count();
18 |
19 | $data = compact('users', 'visitors', 'articles', 'comments');
20 |
21 | return $this->response->json($data);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Api/MeController.php:
--------------------------------------------------------------------------------
1 | validate($request, [
22 | 'id' => 'required|exists:comments,id',
23 | ]);
24 |
25 | $user = auth()->user();
26 |
27 | $comment = Comment::findOrFail($request->id);
28 |
29 | ($type == 'up') ? User::upOrDownVote($user, $comment) : User::upOrDownVote($user, $comment, 'down');
30 |
31 | return $this->response->withNoContent();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Api/PermissionsController.php:
--------------------------------------------------------------------------------
1 | response->collection($permissions);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Api/SystemController.php:
--------------------------------------------------------------------------------
1 | getPdo();
15 |
16 | $version = $pdo->query('select version()')->fetchColumn();
17 |
18 | $data = [
19 | 'server' => $_SERVER['SERVER_SOFTWARE'],
20 | 'http_host' => $_SERVER['HTTP_HOST'],
21 | 'remote_host' => isset($_SERVER['REMOTE_HOST']) ? $_SERVER['REMOTE_HOST'] : $_SERVER['REMOTE_ADDR'],
22 | 'user_agent' => $_SERVER['HTTP_USER_AGENT'],
23 | 'php' => phpversion(),
24 | 'sapi_name' => php_sapi_name(),
25 | 'extensions' => implode(", ", get_loaded_extensions()),
26 | 'db_connection' => isset($_SERVER['DB_CONNECTION']) ? $_SERVER['DB_CONNECTION'] : 'Secret',
27 | 'db_database' => isset($_SERVER['DB_DATABASE']) ? $_SERVER['DB_DATABASE'] : 'Secret',
28 | 'db_version' => $version,
29 | ];
30 |
31 | return $this->response->json($data);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Api/VisitorController.php:
--------------------------------------------------------------------------------
1 |
14 | *
15 | * @param Request $request
16 | *
17 | * @return \Illuminate\Http\JsonResponse
18 | * @throws \Exception
19 | */
20 | public function index(Request $request)
21 | {
22 | $vistors = Visitor::filter($request->all())->orderBy('created_at', 'desc')->paginate(10);
23 |
24 | return $this->response->collection($vistors);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/Http/Controllers/ArticleController.php:
--------------------------------------------------------------------------------
1 | orderBy(config('blog.article.sortColumn'), config('blog.article.sort'))
20 | ->paginate(config('blog.article.number'));
21 |
22 | return view('article.index', compact('articles'));
23 | }
24 |
25 | /**
26 | * Display the article resource by article slug.
27 | *
28 | * @author Huiwang <905130909@qq.com>
29 | *
30 | * @param Request $request
31 | * @param $slug
32 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
33 | */
34 | public function show(Request $request, $slug)
35 | {
36 | $article = Article::checkAuth()->where('slug', $slug)->firstOrFail();
37 |
38 | $article->increment('view_count');
39 |
40 | $ip = $request->getClientIp();
41 |
42 | if ($ip == '::1') {
43 | $ip = '127.0.0.1';
44 | }
45 |
46 | Visitor::log($article->id, $ip);
47 |
48 | return view('article.show', compact('article'));
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Auth/ForgotPasswordController.php:
--------------------------------------------------------------------------------
1 | middleware('guest');
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Auth/LoginController.php:
--------------------------------------------------------------------------------
1 | middleware('guest', ['except' => 'logout']);
39 | }
40 |
41 | /**
42 | * Log the user out of the application.
43 | *
44 | * @param \Illuminate\Http\Request $request
45 | * @return \Illuminate\Http\Response
46 | */
47 | public function logout(Request $request)
48 | {
49 | $this->guard()->logout();
50 |
51 | $request->session()->flush();
52 |
53 | $request->session()->regenerate();
54 |
55 | return redirect('/login');
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Auth/ResetPasswordController.php:
--------------------------------------------------------------------------------
1 | middleware('guest');
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/Http/Controllers/CategoryController.php:
--------------------------------------------------------------------------------
1 | get();
17 |
18 | return view('category.index', compact('categories'));
19 | }
20 |
21 | /**
22 | * Display the category resource by category name.
23 | *
24 | * @param string $category
25 | *
26 | * @return mixed
27 | */
28 | public function show($category)
29 | {
30 | $category = Category::query()->where('name', $category)->first();
31 |
32 | if (!$category) {
33 | abort(404);
34 | }
35 |
36 | $articles = $category->articles;
37 |
38 | return view('category.show', compact('category', 'articles'));
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Controller.php:
--------------------------------------------------------------------------------
1 | get('q'));
30 |
31 | $articles = Article::query()->where('title', 'like', "%{$key}%")
32 | ->orWhere('content', 'like', "%{$key}%")
33 | ->orderBy('published_at', 'desc')
34 | ->get();
35 |
36 | return view('search', compact('articles'));
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/app/Http/Controllers/LinkController.php:
--------------------------------------------------------------------------------
1 | orderBy('created_at', 'desc')->paginate(10);
17 |
18 | return view('link.index', compact('links'));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/Http/Controllers/SettingController.php:
--------------------------------------------------------------------------------
1 | $request->get('email_notify_enabled') ? 'yes' : 'no',
41 | ];
42 |
43 | User::query()->where('id', \Auth::id())->update($input);
44 |
45 | return redirect()->back();
46 | }
47 |
48 | /**
49 | * Display the bindings page.
50 | *
51 | * @return \Illuminate\Http\Response
52 | */
53 | public function binding()
54 | {
55 | return view('setting.binding');
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/app/Http/Controllers/TagController.php:
--------------------------------------------------------------------------------
1 | get();
17 |
18 | return view('tag.index', compact('tags'));
19 | }
20 |
21 | /**
22 | * Display the articles and discussions by the tag.
23 | *
24 | * @param string $tag
25 | *
26 | * @return mixed
27 | */
28 | public function show($tag)
29 | {
30 | $tag = Tag::query()->where('tag', $tag)->first();
31 |
32 | if (!$tag) {
33 | abort(404);
34 | }
35 |
36 | $articles = $tag->articles;
37 | $discussions = $tag->discussions;
38 |
39 | return view('tag.show', compact('tag', 'articles', 'discussions'));
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/Http/Middleware/Authenticate.php:
--------------------------------------------------------------------------------
1 | expectsJson()) {
18 | return route('login');
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/app/Http/Middleware/CheckForMaintenanceMode.php:
--------------------------------------------------------------------------------
1 | is_admin) {
21 | abort(404);
22 | }
23 |
24 | return $next($request);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/Http/Middleware/PermissionMiddleware.php:
--------------------------------------------------------------------------------
1 | guest()) {
13 | throw UnauthorizedException::notLoggedIn();
14 | }
15 |
16 | $permissions = is_array($permission)
17 | ? $permission
18 | : explode('|', $permission);
19 |
20 | foreach ($permissions as $permission) {
21 | if (app('auth')->user()->hasPermissionTo($permission) || app('auth')->user()->isSuperAdmin()) {
22 | return $next($request);
23 | }
24 | }
25 |
26 | throw UnauthorizedException::forPermissions($permissions);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/Http/Middleware/RedirectIfAuthenticated.php:
--------------------------------------------------------------------------------
1 | check()) {
21 | return redirect('/');
22 | }
23 |
24 | return $next($request);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/Http/Middleware/TrimStrings.php:
--------------------------------------------------------------------------------
1 | |string|null
14 | */
15 | protected $proxies;
16 |
17 | /**
18 | * The headers that should be used to detect proxies.
19 | *
20 | * @var int
21 | */
22 | protected $headers =
23 | Request::HEADER_X_FORWARDED_FOR |
24 | Request::HEADER_X_FORWARDED_HOST |
25 | Request::HEADER_X_FORWARDED_PORT |
26 | Request::HEADER_X_FORWARDED_PROTO |
27 | Request::HEADER_X_FORWARDED_AWS_ELB;
28 | }
29 |
--------------------------------------------------------------------------------
/app/Http/Middleware/VerifyCsrfToken.php:
--------------------------------------------------------------------------------
1 | 'required|min:3',
28 | 'subtitle' => 'required|min:3',
29 | 'content' => 'required',
30 | 'category_id' => 'required',
31 | 'published_at' => 'required',
32 | ];
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/Http/Requests/CategoryRequest.php:
--------------------------------------------------------------------------------
1 | 'required|min:2',
28 | 'path' => 'required',
29 | ];
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/Http/Requests/CommentRequest.php:
--------------------------------------------------------------------------------
1 | 'required'
28 | ];
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/Http/Requests/DiscussionRequest.php:
--------------------------------------------------------------------------------
1 | 'required|min:2',
28 | 'content' => 'required',
29 | 'tags' => 'required',
30 | ];
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/Http/Requests/ImageRequest.php:
--------------------------------------------------------------------------------
1 | 'image|mimes:jpeg,jpg,png,gif'
28 | ];
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/Http/Requests/LinkRequest.php:
--------------------------------------------------------------------------------
1 | 'required|min:2',
28 | 'link' => 'required|min:2'
29 | ];
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/Http/Requests/TagRequest.php:
--------------------------------------------------------------------------------
1 | 'required|unique:tags',
28 | 'title' => 'required',
29 | 'meta_description' => 'required'
30 | ];
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/Http/Requests/UserRequest.php:
--------------------------------------------------------------------------------
1 | 'required|unique:users',
28 | 'email' => 'required|email|unique:users',
29 | 'password_confirmation' => 'required',
30 | 'password' => 'required|confirmed',
31 | ];
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/Link.php:
--------------------------------------------------------------------------------
1 |
47 | *
48 | * @param $query
49 | * @return mixed
50 | */
51 | public function scopeCheckAuth($query)
52 | {
53 | if (auth()->check() && auth()->user()->is_admin) {
54 | $query->withoutGlobalScope(StatusScope::class);
55 | }
56 | return $query;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/app/Model.php:
--------------------------------------------------------------------------------
1 | [input_key1, input_key2]].
12 | *
13 | * @var array
14 | */
15 | public $relations = [];
16 |
17 | public function keyword($keyword)
18 | {
19 | return $this->where('title', 'like', "%{$keyword}%")->orWhere('subtitle', 'like', "%{$keyword}%");
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/ModelFilters/CategoryFilter.php:
--------------------------------------------------------------------------------
1 | [input_key1, input_key2]].
12 | *
13 | * @var array
14 | */
15 | public $relations = [];
16 |
17 | public function keyword($keyword)
18 | {
19 | return $this->where('name', 'like', "%{$keyword}%");
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/ModelFilters/CommentFilter.php:
--------------------------------------------------------------------------------
1 | [input_key1, input_key2]].
12 | *
13 | * @var array
14 | */
15 | public $relations = ['user' => 'keyword'];
16 |
17 | public function commentableType($commentableType)
18 | {
19 | return $this->where('commentable_type', $commentableType);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/ModelFilters/DiscussionFilter.php:
--------------------------------------------------------------------------------
1 | [input_key1, input_key2]].
10 | *
11 | * @var array
12 | */
13 | public $relations = [];
14 |
15 | public function keyword($keyword)
16 | {
17 | return $this->where('title', 'like', "%{$keyword}%")
18 | ->orWhereHas('user', function ($query) use ($keyword) {
19 | $query->where('name', 'like', "%{$keyword}%");
20 | });
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/ModelFilters/LinkFilter.php:
--------------------------------------------------------------------------------
1 | [input_key1, input_key2]].
12 | *
13 | * @var array
14 | */
15 | public $relations = [];
16 |
17 | public function keyword($keyword)
18 | {
19 | return $this->where('name', 'like', "%{$keyword}%");
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/ModelFilters/RoleFilter.php:
--------------------------------------------------------------------------------
1 | [input_key1, input_key2]].
12 | *
13 | * @var array
14 | */
15 | public $relations = [];
16 |
17 | public function keyword($keyword)
18 | {
19 | return $this->where('name', 'like', "%{$keyword}%");
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/ModelFilters/TagFilter.php:
--------------------------------------------------------------------------------
1 | [input_key1, input_key2]].
12 | *
13 | * @var array
14 | */
15 | public $relations = [];
16 |
17 | public function keyword($keyword)
18 | {
19 | return $this->where('tag', 'like', "%{$keyword}%")->orWhere('title', 'like', "%{$keyword}%");
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/ModelFilters/UserFilter.php:
--------------------------------------------------------------------------------
1 | [input_key1, input_key2]].
10 | *
11 | * @var array
12 | */
13 | public $relations = [];
14 |
15 | public function keyword($keyword)
16 | {
17 | return $this->where('name', 'like', "%{$keyword}%");
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/ModelFilters/VisitorFilter.php:
--------------------------------------------------------------------------------
1 | [input_key1, input_key2]].
12 | *
13 | * @var array
14 | */
15 | public $relations = [];
16 |
17 | public function keyword($keyword)
18 | {
19 | return $this->where('ip', 'like', "%{$keyword}%")
20 | ->orWhereHas('article', function ($query) use ($keyword) {
21 | $query->where('title', 'like', "%{$keyword}%");
22 | });
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/Policies/ArticlePolicy.php:
--------------------------------------------------------------------------------
1 | check() && !$article->is_draft;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/Policies/CommentPolicy.php:
--------------------------------------------------------------------------------
1 | user_id === $user->id;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/Policies/DiscussionPolicy.php:
--------------------------------------------------------------------------------
1 | id === $discussion->user_id;
21 | }
22 |
23 | /**
24 | * Determine whether the user can delete the discussion.
25 | *
26 | * @param \App\User $user
27 | * @param \App\Discussion $discussion
28 | * @return mixed
29 | */
30 | public function delete(User $user, Discussion $discussion)
31 | {
32 | return false;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/Policies/Policy.php:
--------------------------------------------------------------------------------
1 | is_admin) {
15 | return true;
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/Policies/UserPolicy.php:
--------------------------------------------------------------------------------
1 | id === $user->id;
19 | }
20 |
21 | /**
22 | * Determine whether the current user can delete the user.
23 | *
24 | * @param \App\User $currentUser
25 | * @param \App\User $user
26 | * @return mixed
27 | */
28 | public function delete(User $currentUser, User $user)
29 | {
30 | return false;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/Providers/AppServiceProvider.php:
--------------------------------------------------------------------------------
1 | Discussion::class,
28 | 'articles' => Article::class,
29 | ]);
30 |
31 | Schema::defaultStringLength(191);
32 | Paginator::useBootstrap();
33 | }
34 |
35 | /**
36 | * Register any application services.
37 | *
38 | * @return void
39 | */
40 | public function register()
41 | {
42 | $this->app->singleton('uploader', function ($app) {
43 | $config = config('filesystems.default', 'public');
44 |
45 | if ($config == 'upyun') {
46 | return new UpyunManager();
47 | }
48 |
49 | return new BaseManager();
50 | });
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/Providers/AuthServiceProvider.php:
--------------------------------------------------------------------------------
1 | \App\Policies\UserPolicy::class,
19 | \App\Article::class => \App\Policies\ArticlePolicy::class,
20 | \App\Comment::class => \App\Policies\CommentPolicy::class,
21 | \App\Discussion::class => \App\Policies\DiscussionPolicy::class,
22 | ];
23 |
24 | /**
25 | * Register any authentication / authorization services.
26 | *
27 | * @return void
28 | */
29 | public function boot()
30 | {
31 | $this->registerPolicies();
32 |
33 | Passport::routes();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/Providers/BroadcastServiceProvider.php:
--------------------------------------------------------------------------------
1 | [
19 | SendEmailVerificationNotification::class,
20 | ],
21 | ];
22 |
23 | /**
24 | * Register any events for your application.
25 | *
26 | * @return void
27 | */
28 | public function boot()
29 | {
30 | parent::boot();
31 |
32 | //
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/Scopes/DraftScope.php:
--------------------------------------------------------------------------------
1 | where('is_draft', 0);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/Scopes/StatusScope.php:
--------------------------------------------------------------------------------
1 | where('status', 1);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/Tag.php:
--------------------------------------------------------------------------------
1 | morphedByMany(Article::class, 'taggable');
38 | }
39 |
40 | /**
41 | * Get all of the discussions that are assigned this tag.
42 | *
43 | * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
44 | */
45 | public function discussions()
46 | {
47 | return $this->morphedByMany(Discussion::class, 'taggable');
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/app/Tools/IP.php:
--------------------------------------------------------------------------------
1 | request = $request;
24 | }
25 |
26 | /**
27 | * Get the client ip.
28 | *
29 | * @return mixed|string
30 | */
31 | public function get()
32 | {
33 | $ip = $this->request->getClientIp();
34 |
35 | if($ip == '::1') {
36 | $ip = '127.0.0.1';
37 | }
38 |
39 | return $ip;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/Tools/Markdowner.php:
--------------------------------------------------------------------------------
1 | htmlConverter = new HtmlConverter();
26 |
27 | $this->markdownConverter = new Parsedown();
28 | }
29 |
30 | /**
31 | * Convert Markdown To Html.
32 | *
33 | * @param $markdown
34 | * @return string
35 | */
36 | public function convertMarkdownToHtml($markdown)
37 | {
38 | return $this->markdownConverter
39 | ->setBreaksEnabled(true)
40 | ->text($markdown);
41 | }
42 |
43 | /**
44 | * Convert Html To Markdown.
45 | *
46 | * @param $html
47 | * @return string
48 | */
49 | public function convertHtmlToMarkdown($html)
50 | {
51 | return $this->htmlConverter->convert($html);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/app/Traits/BelongsToUser.php:
--------------------------------------------------------------------------------
1 | belongsTo(User::class);
17 | }
18 |
19 | public static function bootBelongsToUser()
20 | {
21 | static::saving(function ($model) {
22 | $model->user_id = $model->user_id ?? \Auth::id();
23 | });
24 | }
25 | }
--------------------------------------------------------------------------------
/app/Traits/HasComments.php:
--------------------------------------------------------------------------------
1 | morphMany(Comment::class, 'commentable');
17 | }
18 | }
--------------------------------------------------------------------------------
/app/Traits/HasTags.php:
--------------------------------------------------------------------------------
1 | morphToMany(Tag::class, 'taggable');
17 | }
18 | }
--------------------------------------------------------------------------------
/app/Transformers/CategoryTransformer.php:
--------------------------------------------------------------------------------
1 | $category->id,
14 | 'name' => $category->name,
15 | 'path' => $category->path,
16 | 'description' => $category->description,
17 | 'status' => $category->status,
18 | 'created_at' => $category->created_at->toDateTimeString(),
19 | ];
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/Transformers/EmptyTransformer.php:
--------------------------------------------------------------------------------
1 | $link->id,
14 | 'name' => $link->name,
15 | 'image' => $link->image,
16 | 'link' => $link->link,
17 | 'status' => (bool) $link->status,
18 | 'created_at' => $link->created_at->toDateTimeString(),
19 | ];
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/Transformers/PermissionTransformer.php:
--------------------------------------------------------------------------------
1 | $permission->id,
14 | 'name' => $permission->name,
15 | 'label' => trans('permissions.' . $permission->name)
16 | ];
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/Transformers/RoleTransformer.php:
--------------------------------------------------------------------------------
1 | $role->id,
18 | 'name' => $role->name,
19 | 'guard_name' => $role->guard_name,
20 | 'permission_ids'=> $role->permissions->pluck('id'),
21 | 'created_at' => $role->created_at->toDateTimeString(),
22 | ];
23 | }
24 |
25 | /**
26 | * Include Category
27 | *
28 | * @param Role $role
29 | * @return \League\Fractal\Resource\Collection
30 | */
31 | public function includePermissions(Role $role)
32 | {
33 | if ($permissions = $role->permissions) {
34 | return $this->collection($permissions, new PermissionTransformer);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/Transformers/TagTransformer.php:
--------------------------------------------------------------------------------
1 | $tag->id,
14 | 'tag' => $tag->tag,
15 | 'title' => $tag->title,
16 | 'meta_description' => $tag->meta_description,
17 | 'status' => $tag->status,
18 | 'created_at' => $tag->created_at->toDateTimeString(),
19 | ];
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/Transformers/UserTransformer.php:
--------------------------------------------------------------------------------
1 | $user->id,
19 | 'avatar' => $user->avatar,
20 | 'name' => $user->name,
21 | 'status' => $user->status,
22 | 'email' => $user->email,
23 | 'nickname' => $user->nickname,
24 | 'is_admin' => $user->is_admin,
25 | 'github_name' => $user->github_name,
26 | 'website' => $user->website,
27 | 'description' => $user->description,
28 | 'created_at' => $user->created_at->toDateTimeString(),
29 | ];
30 | }
31 |
32 | /**
33 | * Include Role
34 | *
35 | * @param User $user
36 | * @return \League\Fractal\Resource\Collection
37 | */
38 | public function includeRoles(User $user)
39 | {
40 | if ($roles = $user->roles) {
41 | return $this->collection($roles, new RoleTransformer);
42 | }
43 | }
44 |
45 | /**
46 | * Include Permission
47 | *
48 | * @param User $user
49 | * @return \League\Fractal\Resource\Collection
50 | */
51 | public function includePermissions(User $user)
52 | {
53 | if ($permissions = $user->permissions) {
54 | return $this->collection($permissions, new PermissionTransformer);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/app/Transformers/VisitorTransformer.php:
--------------------------------------------------------------------------------
1 | $visitor->id,
14 | 'article' => [ 'title' => isset($visitor->article) ? $visitor->article->title : 'null' ],
15 | 'ip' => $visitor->ip,
16 | 'country' => $visitor->country,
17 | 'clicks' => $visitor->clicks,
18 | 'created_at' => $visitor->created_at->toDateTimeString(),
19 | ];
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/Visitor.php:
--------------------------------------------------------------------------------
1 | belongsTo(Article::class);
26 | }
27 |
28 | /**
29 | * 记录访问记录.
30 | *
31 | * @author Huiwang <905130909@qq.com>
32 | *
33 | * @param $articleId
34 | * @param $ip
35 | *
36 | * @return Visitor|Model|null|object
37 | */
38 | public static function log($articleId, $ip)
39 | {
40 | $log = self::query()->where('article_id', $articleId)->where('ip', $ip)->first();
41 | if ($log) {
42 | $log->increment('clicks');
43 | } else {
44 | $data = [
45 | 'ip' => $ip,
46 | 'article_id' => $articleId,
47 | 'clicks' => 1,
48 | ];
49 | $log = self::create($data);
50 | }
51 |
52 | return $log;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/bootstrap/cache/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/config/compile.php:
--------------------------------------------------------------------------------
1 | [
17 | //
18 | ],
19 |
20 | /*
21 | |--------------------------------------------------------------------------
22 | | Compiled File Providers
23 | |--------------------------------------------------------------------------
24 | |
25 | | Here you may list service providers which define a "compiles" function
26 | | that returns additional files that should be compiled, providing an
27 | | easy way to get common files from any packages you are utilizing.
28 | |
29 | */
30 |
31 | 'providers' => [
32 | //
33 | ],
34 |
35 | ];
36 |
--------------------------------------------------------------------------------
/config/cors.php:
--------------------------------------------------------------------------------
1 | ['api/*'],
19 |
20 | 'allowed_methods' => ['*'],
21 |
22 | 'allowed_origins' => ['*'],
23 |
24 | 'allowed_origins_patterns' => [],
25 |
26 | 'allowed_headers' => ['*'],
27 |
28 | 'exposed_headers' => [],
29 |
30 | 'max_age' => 0,
31 |
32 | 'supports_credentials' => false,
33 |
34 | ];
--------------------------------------------------------------------------------
/config/eloquentfilter.php:
--------------------------------------------------------------------------------
1 | 'App\\ModelFilters\\',
15 |
16 | /*
17 | |--------------------------------------------------------------------------
18 | | Custom generator stub
19 | |--------------------------------------------------------------------------
20 | |
21 | | If you want to override the default stub this package provides
22 | | you can enter the path to your own at this point
23 | |
24 | */
25 | // 'generator' => [
26 | // 'stub' => app_path('stubs/modelfilter.stub')
27 | // ]
28 |
29 | /*
30 | |--------------------------------------------------------------------------
31 | | Default Paginator Limit For `paginateFilter` and `simplePaginateFilter`
32 | |--------------------------------------------------------------------------
33 | |
34 | | Set paginate limit
35 | |
36 | */
37 | 'paginate_limit' => env('PAGINATION_LIMIT_DEFAULT',15)
38 |
39 | ];
40 |
--------------------------------------------------------------------------------
/config/hashing.php:
--------------------------------------------------------------------------------
1 | 'bcrypt',
19 |
20 | /*
21 | |--------------------------------------------------------------------------
22 | | Bcrypt Options
23 | |--------------------------------------------------------------------------
24 | |
25 | | Here you may specify the configuration options that should be used when
26 | | passwords are hashed using the Bcrypt algorithm. This will allow you
27 | | to control the amount of time it takes to hash the given password.
28 | |
29 | */
30 |
31 | 'bcrypt' => [
32 | 'rounds' => env('BCRYPT_ROUNDS', 10),
33 | ],
34 |
35 | /*
36 | |--------------------------------------------------------------------------
37 | | Argon Options
38 | |--------------------------------------------------------------------------
39 | |
40 | | Here you may specify the configuration options that should be used when
41 | | passwords are hashed using the Argon algorithm. These will allow you
42 | | to control the amount of time it takes to hash the given password.
43 | |
44 | */
45 |
46 | 'argon' => [
47 | 'memory' => 1024,
48 | 'threads' => 2,
49 | 'time' => 2,
50 | ],
51 |
52 | ];
--------------------------------------------------------------------------------
/config/image.php:
--------------------------------------------------------------------------------
1 | 'gd'
19 |
20 | );
21 |
--------------------------------------------------------------------------------
/config/services.php:
--------------------------------------------------------------------------------
1 | [
18 | 'domain' => env('MAILGUN_DOMAIN'),
19 | 'secret' => env('MAILGUN_SECRET'),
20 | 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
21 | ],
22 |
23 | 'postmark' => [
24 | 'token' => env('POSTMARK_TOKEN'),
25 | ],
26 |
27 | 'ses' => [
28 | 'key' => env('AWS_ACCESS_KEY_ID'),
29 | 'secret' => env('AWS_SECRET_ACCESS_KEY'),
30 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
31 | ],
32 |
33 | ];
--------------------------------------------------------------------------------
/config/view.php:
--------------------------------------------------------------------------------
1 | [
17 | resource_path('views'),
18 | ],
19 |
20 | /*
21 | |--------------------------------------------------------------------------
22 | | Compiled View Path
23 | |--------------------------------------------------------------------------
24 | |
25 | | This option determines where all the compiled Blade templates will be
26 | | stored for your application. Typically, this is within the storage
27 | | directory. However, as usual, you are free to change this value.
28 | |
29 | */
30 |
31 | 'compiled' => env(
32 | 'VIEW_COMPILED_PATH',
33 | realpath(storage_path('framework/views'))
34 | ),
35 |
36 | ];
--------------------------------------------------------------------------------
/config/vote.php:
--------------------------------------------------------------------------------
1 | 'votes',
6 |
7 | 'user_foreign_key' => 'user_id',
8 |
9 | 'vote_model' => \Jcc\LaravelVote\Vote::class,
10 | ];
11 |
--------------------------------------------------------------------------------
/database/.gitignore:
--------------------------------------------------------------------------------
1 | *.sqlite
2 |
--------------------------------------------------------------------------------
/database/migrations/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/database/migrations/2014_10_12_000000_create_users_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->string('name')->unique();
19 | $table->string('nickname')->nullable();
20 | $table->text('avatar')->nullable();
21 | $table->string('email')->unique();
22 | $table->string('confirm_code', 64)->unique()->nullable();
23 | $table->tinyInteger('status')->default(false);
24 | $table->boolean('is_admin')->default(false);
25 | $table->string('password');
26 | $table->string('github_id')->nullable();
27 | $table->string('github_name')->nullable();
28 | $table->string('github_url')->nullable();
29 | $table->string('weibo_name')->nullable();
30 | $table->string('weibo_link')->nullable();
31 | $table->string('website')->nullable();
32 | $table->string('description')->nullable();
33 | $table->enum('email_notify_enabled', ['yes', 'no'])->default('yes')->index();
34 | $table->rememberToken();
35 | $table->timestamps();
36 | $table->softDeletes();
37 | });
38 | }
39 |
40 | /**
41 | * Reverse the migrations.
42 | *
43 | * @return void
44 | */
45 | public function down()
46 | {
47 | Schema::drop('users');
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/database/migrations/2014_10_12_100000_create_password_resets_table.php:
--------------------------------------------------------------------------------
1 | string('email')->index();
18 | $table->string('token')->index();
19 | $table->timestamp('created_at')->nullable();
20 | });
21 | }
22 |
23 | /**
24 | * Reverse the migrations.
25 | *
26 | * @return void
27 | */
28 | public function down()
29 | {
30 | Schema::drop('password_resets');
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/database/migrations/2016_09_02_065857_create_articles_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->unsignedBigInteger('category_id');
19 | $table->unsignedBigInteger('user_id');
20 | $table->unsignedBigInteger('last_user_id');
21 | $table->string('slug')->unique();
22 | $table->string('title');
23 | $table->string('subtitle');
24 | // $table->json('content');
25 | $table->longText('content');
26 | $table->string('page_image')->nullable();
27 | $table->string('meta_description')->nullable();
28 | $table->boolean('is_original')->default(false);
29 | $table->boolean('is_draft')->default(false);
30 | $table->integer('view_count')->unsigned()->default(0)->index();
31 | $table->timestamp('published_at')->nullable();
32 | $table->timestamps();
33 | $table->softDeletes();
34 | });
35 | }
36 |
37 | /**
38 | * Reverse the migrations.
39 | *
40 | * @return void
41 | */
42 | public function down()
43 | {
44 | Schema::dropIfExists('articles');
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/database/migrations/2016_09_02_065920_create_tags_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->string('tag')->unique();
19 | $table->string('title');
20 | $table->string('meta_description');
21 | $table->timestamps();
22 | $table->softDeletes();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('tags');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/database/migrations/2016_09_02_065952_create_visitors_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->unsignedBigInteger('article_id');
19 | $table->foreign('article_id')->references('id')->on('articles')->onDelete('cascade');
20 | $table->string('ip', 32);
21 | $table->string('country')->nullable();
22 | $table->integer('clicks')->unsigned()->default(1);
23 | $table->timestamps();
24 | });
25 | }
26 |
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::dropIfExists('visitors');
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/database/migrations/2016_09_02_070119_create_categories_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->unsignedBigInteger('parent_id')->default(0);
19 | $table->string('name');
20 | $table->string('path');
21 | $table->string('description')->nullable();
22 | $table->string('image_url')->nullable();
23 | $table->timestamps();
24 | });
25 | }
26 |
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::dropIfExists('categories');
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/database/migrations/2016_09_02_070132_create_discussions_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->unsignedBigInteger('user_id');
19 | $table->unsignedBigInteger('last_user_id');
20 | $table->string('title');
21 | // $table->json('content');
22 | $table->text('content');
23 | $table->tinyInteger('status')->default(false);
24 | $table->timestamps();
25 | $table->softDeletes();
26 | });
27 | }
28 |
29 | /**
30 | * Reverse the migrations.
31 | *
32 | * @return void
33 | */
34 | public function down()
35 | {
36 | Schema::dropIfExists('discussions');
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/database/migrations/2016_09_02_070151_create_comments_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->unsignedBigInteger('user_id');
19 | $table->unsignedBigInteger('commentable_id');
20 | $table->char('commentable_type');
21 | // $table->json('content');
22 | $table->text('content');
23 | $table->timestamps();
24 | $table->softDeletes();
25 | });
26 | }
27 |
28 | /**
29 | * Reverse the migrations.
30 | *
31 | * @return void
32 | */
33 | public function down()
34 | {
35 | Schema::dropIfExists('comments');
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/database/migrations/2016_09_13_022056_create_links_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->string('name')->index();
19 | $table->string('link')->index();
20 | $table->text('image')->nullable();
21 | $table->boolean('status')->default(true);
22 | $table->timestamps();
23 | $table->softDeletes();
24 | });
25 | }
26 |
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::dropIfExists('links');
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/database/migrations/2016_11_11_163610_create_taggables_table.php:
--------------------------------------------------------------------------------
1 | unsignedBigInteger('tag_id')->index();
18 | $table->unsignedBigInteger('taggable_id')->index();
19 | $table->string('taggable_type')->index();
20 | });
21 | }
22 |
23 | /**
24 | * Reverse the migrations.
25 | *
26 | * @return void
27 | */
28 | public function down()
29 | {
30 | Schema::dropIfExists('taggables');
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/database/migrations/2016_12_11_153312_create_followers_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->unsignedBigInteger('user_id');
19 | $table->unsignedBigInteger('follow_id');
20 | $table->timestamps();
21 | });
22 | }
23 |
24 | /**
25 | * Reverse the migrations.
26 | *
27 | * @return void
28 | */
29 | public function down()
30 | {
31 | Schema::dropIfExists('followers');
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/database/migrations/2016_12_12_171655_create_notifications_table.php:
--------------------------------------------------------------------------------
1 | uuid('id')->primary();
17 | $table->string('type');
18 | $table->morphs('notifiable');
19 | $table->text('data');
20 | $table->timestamp('read_at')->nullable();
21 | $table->timestamps();
22 | });
23 | }
24 |
25 | /**
26 | * Reverse the migrations.
27 | *
28 | * @return void
29 | */
30 | public function down()
31 | {
32 | Schema::dropIfExists('notifications');
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/database/migrations/2016_12_12_205419_create_failed_jobs_table.php:
--------------------------------------------------------------------------------
1 | string('uuid')->after('id')->nullable()->unique();
18 | $table->text('connection');
19 | $table->text('queue');
20 | $table->longText('payload');
21 | $table->longText('exception');
22 | $table->timestamp('failed_at')->useCurrent();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('failed_jobs');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/database/seeds/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/database/seeds/ArticlesTableSeeder.php:
--------------------------------------------------------------------------------
1 | create();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/database/seeds/CategoriesTableSeeder.php:
--------------------------------------------------------------------------------
1 | create();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/database/seeds/CommentsTableSeeder.php:
--------------------------------------------------------------------------------
1 | create();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/database/seeds/DatabaseSeeder.php:
--------------------------------------------------------------------------------
1 | call(UsersTableSeeder::class);
17 | $this->call(CategoriesTableSeeder::class);
18 | $this->call(ArticlesTableSeeder::class);
19 | $this->call(DiscussionsTableSeeder::class);
20 | $this->call(CommentsTableSeeder::class);
21 | $this->call(TagsTableSeeder::class);
22 | $this->call(LinksTableSeeder::class);
23 | $this->call(VisitorsTableSeeder::class);
24 | $this->call(PermissionTableSeeder::class);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/database/seeds/DiscussionsTableSeeder.php:
--------------------------------------------------------------------------------
1 | create();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/database/seeds/LinksTableSeeder.php:
--------------------------------------------------------------------------------
1 | create();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/database/seeds/TagsTableSeeder.php:
--------------------------------------------------------------------------------
1 | create();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/database/seeds/UsersTableSeeder.php:
--------------------------------------------------------------------------------
1 | config('blog.admin_name'),
22 | 'email' => config('blog.admin_email'),
23 | 'password' => Hash::make(config('blog.admin_password')),
24 | 'status' => true,
25 | 'is_admin' => true,
26 | 'confirm_code' => Str::random(64),
27 | 'created_at' => Carbon::now(),
28 | 'updated_at' => Carbon::now()
29 | ]
30 | ];
31 |
32 | DB::table('users')->insert($users);
33 |
34 | factory(User::class, 10)->create();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/database/seeds/VisitorsTableSeeder.php:
--------------------------------------------------------------------------------
1 | create();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # run migration and app
4 | php artisan blog:install
5 | php artisan serve --host 0.0.0.0
6 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
';
12 | });
13 |
14 | swal({
15 | title: "Error Text!",
16 | type: 'error',
17 | html: content
18 | });
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/resources/js/config/toastr.js:
--------------------------------------------------------------------------------
1 | export default {
2 | positionClass: "toast-bottom-right",
3 | showDuration: "300",
4 | hideDuration: "1000",
5 | timeOut: "5000",
6 | extendedTimeOut: "1000",
7 | showEasing: "swing",
8 | hideEasing: "linear",
9 | showMethod: "fadeIn",
10 | hideMethod: "fadeOut"
11 | }
12 |
--------------------------------------------------------------------------------
/resources/js/dashboard/components/Form.vue:
--------------------------------------------------------------------------------
1 |
2 | {{ title }}
6 |
7 |