Compare commits
No commits in common. "old-api" and "main" have entirely different histories.
18
.editorconfig
Normal file
18
.editorconfig
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[*.{yml,yaml}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[docker-compose.yml]
|
||||||
|
indent_size = 4
|
18
.env.example
18
.env.example
@ -1,10 +1,16 @@
|
|||||||
APP_NAME="KamilCraft.com"
|
APP_NAME=KamilCraftAPI
|
||||||
|
APP_ENV=local
|
||||||
|
APP_KEY=
|
||||||
APP_DEBUG=true
|
APP_DEBUG=true
|
||||||
APP_URL=http://127.0.0.1
|
APP_URL=http://localhost
|
||||||
|
|
||||||
DB_CONNECTION=mysql
|
DB_CONNECTION=mysql
|
||||||
DB_HOST=127.0.0.1
|
DB_HOST=kamilcraft-api_db
|
||||||
DB_PORT=3306
|
DB_PORT=3306
|
||||||
DB_DATABASE=test
|
DB_DATABASE=kamilcraft-api
|
||||||
DB_USERNAME=root
|
DB_USERNAME=kamilcraft-api
|
||||||
DB_PASSWORD=
|
DB_PASSWORD=password
|
||||||
|
|
||||||
|
EXTERNAL_WEBSERVER_PORT=80
|
||||||
|
CURRENT_UID=1000
|
||||||
|
XDG_CONFIG_HOME=/tmp
|
||||||
|
5
.gitattributes
vendored
Normal file
5
.gitattributes
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
* text=auto
|
||||||
|
*.css linguist-vendored
|
||||||
|
*.scss linguist-vendored
|
||||||
|
*.js linguist-vendored
|
||||||
|
CHANGELOG.md export-ignore
|
16
.gitignore
vendored
16
.gitignore
vendored
@ -1,3 +1,15 @@
|
|||||||
.idea
|
/.idea
|
||||||
vendor
|
/.vscode
|
||||||
|
/node_modules
|
||||||
|
/public/storage
|
||||||
|
/storage/*.key
|
||||||
|
/vendor
|
||||||
|
/.composer
|
||||||
.env
|
.env
|
||||||
|
.env.backup
|
||||||
|
.phpunit.result.cache
|
||||||
|
docker-compose.override.yml
|
||||||
|
Homestead.json
|
||||||
|
Homestead.yaml
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
14
.styleci.yml
Normal file
14
.styleci.yml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
php:
|
||||||
|
preset: laravel
|
||||||
|
version: 8
|
||||||
|
disabled:
|
||||||
|
- no_unused_imports
|
||||||
|
finder:
|
||||||
|
not-name:
|
||||||
|
- index.php
|
||||||
|
- server.php
|
||||||
|
js:
|
||||||
|
finder:
|
||||||
|
not-name:
|
||||||
|
- webpack.mix.js
|
||||||
|
css: true
|
21
LICENCE
Normal file
21
LICENCE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License
|
||||||
|
|
||||||
|
Copyright 2022 Kamil Niemczycki
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
55
README.md
55
README.md
@ -1,22 +1,53 @@
|
|||||||
# KamilCraftApi
|
# KamilCraftAPI
|
||||||
|
|
||||||
API for kamilcraft.com projects
|
API for kamilcraft.com projects
|
||||||
|
|
||||||
## Installation
|
## Requirements
|
||||||
|
|
||||||
### Required
|
### Required
|
||||||
|
|
||||||
* PHP 8.0 or later
|
* Docker 20.10.x (Engine) or later
|
||||||
* Composer 2.3.x or later
|
|
||||||
|
|
||||||
### Installation of dependencies
|
### Optional
|
||||||
|
|
||||||
```shell
|
* PHP 8.1.x or later
|
||||||
composer install
|
* Composer 2.4.x or later
|
||||||
```
|
* Nodejs 18.14.x or later
|
||||||
|
|
||||||
## Launching
|
## Preparation and installation
|
||||||
|
|
||||||
```shell
|
1) Copy the contents of the .env.example file into .env
|
||||||
php -S localhost:80 public/index.php
|
```shell
|
||||||
```
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
2) Build the image needed for Laravel and Node.js
|
||||||
|
```shell
|
||||||
|
docker-compose build --no-cache --pull
|
||||||
|
```
|
||||||
|
|
||||||
|
3) Run the images prepared in ``docker-compose.yml``
|
||||||
|
```shell
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
4) Install the dependencies needed for Laravel and Nodejs
|
||||||
|
```shell
|
||||||
|
docker-compose exec -u "$(id -u):$(id -g)" php composer install
|
||||||
|
```
|
||||||
|
```shell
|
||||||
|
docker-compose run --rm -u "$(id -u):$(id -g)" npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
5) Key and data generation
|
||||||
|
```shell
|
||||||
|
docker-compose exec -u "$(id -u):$(id -g)" php php artisan key:generate
|
||||||
|
```
|
||||||
|
```shell
|
||||||
|
docker-compose exec -u "$(id -u):$(id -g)" php php artisan migrate:fresh --seed
|
||||||
|
```
|
||||||
|
```shell
|
||||||
|
docker-compose run --rm -u "$(id -u):$(id -g)" npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
6) Go to ``http://localhost/dashboard`` in your browser.
|
||||||
|
32
app/Console/Kernel.php
Normal file
32
app/Console/Kernel.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console;
|
||||||
|
|
||||||
|
use Illuminate\Console\Scheduling\Schedule;
|
||||||
|
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||||
|
|
||||||
|
class Kernel extends ConsoleKernel
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Define the application's command schedule.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function schedule(Schedule $schedule)
|
||||||
|
{
|
||||||
|
// $schedule->command('inspire')->hourly();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the commands for the application.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function commands()
|
||||||
|
{
|
||||||
|
$this->load(__DIR__.'/Commands');
|
||||||
|
|
||||||
|
require base_path('routes/console.php');
|
||||||
|
}
|
||||||
|
}
|
@ -1,43 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace KamilCraftApi\App\Controllers;
|
|
||||||
|
|
||||||
use KamilCraftApi\App\Models\Category;
|
|
||||||
use KamilCraftApi\Request\Request;
|
|
||||||
use KamilCraftApi\Response;
|
|
||||||
|
|
||||||
class CategoriesController extends Controller
|
|
||||||
{
|
|
||||||
private Category $category;
|
|
||||||
|
|
||||||
public function __construct(Request $request) {
|
|
||||||
parent::__construct();
|
|
||||||
$this->category = new Category($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function showWhereName(string $slug): Response
|
|
||||||
{
|
|
||||||
if ( ! ($category = $this->category->getCategoryWhereName($slug)) ) {
|
|
||||||
return (new Response())->json([
|
|
||||||
'message' => 'Not found category'
|
|
||||||
], 404);
|
|
||||||
}
|
|
||||||
return (new Response())->json($category);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function show(int $id): Response
|
|
||||||
{
|
|
||||||
if ( ! ($category = $this->category->getCategory($id)) ) {
|
|
||||||
return (new Response())->json([
|
|
||||||
'message' => 'Not found category'
|
|
||||||
], 404);
|
|
||||||
}
|
|
||||||
return (new Response())->json($category);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __invoke(): Response
|
|
||||||
{
|
|
||||||
$categories = $this->category;
|
|
||||||
return (new Response())->json($categories());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace KamilCraftApi\App\Controllers;
|
|
||||||
|
|
||||||
use KamilCraftApi\Interfaces\ControllerInterface;
|
|
||||||
use KamilCraftApi\Response;
|
|
||||||
|
|
||||||
class Controller implements ControllerInterface
|
|
||||||
{
|
|
||||||
private Response $response;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->response = new Response();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function response(): Response
|
|
||||||
{
|
|
||||||
return $this->response;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace KamilCraftApi\App\Controllers;
|
|
||||||
|
|
||||||
use KamilCraftApi\Interfaces\ControllerInterface;
|
|
||||||
use KamilCraftApi\Request\Request;
|
|
||||||
use KamilCraftApi\Response;
|
|
||||||
|
|
||||||
class HomeController implements ControllerInterface
|
|
||||||
{
|
|
||||||
public function __invoke(Request $request): Response
|
|
||||||
{
|
|
||||||
return (new Response())->json((object)[
|
|
||||||
'message' => 'Hello World'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace KamilCraftApi\App\Controllers;
|
|
||||||
|
|
||||||
use KamilCraftApi\App\Models\Project;
|
|
||||||
use KamilCraftApi\Response;
|
|
||||||
|
|
||||||
class ProjectController extends Controller
|
|
||||||
{
|
|
||||||
private Project $project;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
parent::__construct();
|
|
||||||
$this->project = new Project();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function showWhereCategory(string $category): Response
|
|
||||||
{
|
|
||||||
$projects = $this->project->getProjectWhereCategory($category);
|
|
||||||
return (new Response())->json($projects);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function show(int $id): Response
|
|
||||||
{
|
|
||||||
if ( ! ($project = $this->project->getProject($id)) ) {
|
|
||||||
return (new Response())->json([
|
|
||||||
'message' => 'Not found project'
|
|
||||||
], 404);
|
|
||||||
}
|
|
||||||
return (new Response())->json($project);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __invoke(): Response
|
|
||||||
{
|
|
||||||
$projects = $this->project;
|
|
||||||
return (new Response())->json($projects());
|
|
||||||
}
|
|
||||||
}
|
|
41
app/Exceptions/Handler.php
Normal file
41
app/Exceptions/Handler.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exceptions;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class Handler extends ExceptionHandler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A list of the exception types that are not reported.
|
||||||
|
*
|
||||||
|
* @var array<int, class-string<Throwable>>
|
||||||
|
*/
|
||||||
|
protected $dontReport = [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of the inputs that are never flashed for validation exceptions.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $dontFlash = [
|
||||||
|
'current_password',
|
||||||
|
'password',
|
||||||
|
'password_confirmation',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the exception handling callbacks for the application.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
$this->reportable(function (Throwable $e) {
|
||||||
|
//
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
29
app/Http/Controllers/Api/CategoryController.php
Normal file
29
app/Http/Controllers/Api/CategoryController.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Http\Resources\CategoryResource;
|
||||||
|
use App\Repository\Interfaces\CategoryRepository;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
|
||||||
|
class CategoryController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private CategoryRepository $categoryRepository
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function index(): Collection
|
||||||
|
{
|
||||||
|
return $this->categoryRepository->all();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function showWhereSlug(string $category): CategoryResource
|
||||||
|
{
|
||||||
|
return $this->categoryRepository->get($category);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
36
app/Http/Controllers/Api/ProjectController.php
Normal file
36
app/Http/Controllers/Api/ProjectController.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Repository\Interfaces\ProjectRepository;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class ProjectController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private ProjectRepository $projectRepository
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'category' => 'nullable|string|exists:categories,slug'
|
||||||
|
]);
|
||||||
|
$filters = [];
|
||||||
|
if ($request->has('category') && ($category = $request->get('category')) !== '') {
|
||||||
|
$filters['category'] = $category;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->projectRepository->all($filters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(int $project)
|
||||||
|
{
|
||||||
|
return $this->projectRepository->get($project);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
54
app/Http/Controllers/Auth/LoginController.php
Normal file
54
app/Http/Controllers/Auth/LoginController.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Auth;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
class LoginController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function authenticate(Request $request)
|
||||||
|
{
|
||||||
|
if (Auth::check())
|
||||||
|
return redirect()->route('admin.home');
|
||||||
|
|
||||||
|
$credentials = $request->validate([
|
||||||
|
'email' => ['required', 'email'],
|
||||||
|
'password' => ['required'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (Auth::attempt($credentials)) {
|
||||||
|
$request->session()->regenerate();
|
||||||
|
return redirect()->route('admin.home');
|
||||||
|
}
|
||||||
|
|
||||||
|
return back()->withErrors([
|
||||||
|
'email' => 'The provided credentials do not match our records.',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function logout()
|
||||||
|
{
|
||||||
|
if (Auth::check()) {
|
||||||
|
Auth::logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('admin.auth.login');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function login(): View|RedirectResponse
|
||||||
|
{
|
||||||
|
if (Auth::check())
|
||||||
|
return redirect()->route('admin.home');
|
||||||
|
|
||||||
|
return view('auth.login');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
13
app/Http/Controllers/Controller.php
Normal file
13
app/Http/Controllers/Controller.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
|
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||||
|
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||||
|
use Illuminate\Routing\Controller as BaseController;
|
||||||
|
|
||||||
|
class Controller extends BaseController
|
||||||
|
{
|
||||||
|
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||||
|
}
|
29
app/Http/Controllers/Dashboard/AdminPanelController.php
Normal file
29
app/Http/Controllers/Dashboard/AdminPanelController.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Dashboard;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Repository\Interfaces\CategoryRepository;
|
||||||
|
use App\Repository\Interfaces\ProjectRepository;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
class AdminPanelController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private CategoryRepository $categoryRepository,
|
||||||
|
private ProjectRepository $projectRepository
|
||||||
|
) {
|
||||||
|
$this->categoryRepository->auth = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __invoke(Request $request): View
|
||||||
|
{
|
||||||
|
$categories = $this->categoryRepository->all();
|
||||||
|
$projects = $this->projectRepository->all();
|
||||||
|
|
||||||
|
return view('dashboard.home', compact('categories', 'projects'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
63
app/Http/Controllers/Dashboard/CategoryController.php
Normal file
63
app/Http/Controllers/Dashboard/CategoryController.php
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Dashboard;
|
||||||
|
|
||||||
|
use App\Http\Requests\CategoryRequest;
|
||||||
|
use App\Models\Category;
|
||||||
|
use App\Repository\Interfaces\CategoryRepository;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
class CategoryController
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private CategoryRepository $categoryRepository
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function update(CategoryRequest $request, Category $category)
|
||||||
|
{
|
||||||
|
$validate = $request->validated();
|
||||||
|
if ($this->categoryRepository->update($category, $validate)) {
|
||||||
|
return back()->with('message', 'Zaktualizowano kategorię!');
|
||||||
|
}
|
||||||
|
|
||||||
|
return back()->withError(['message_error', 'Wystąpił błąd podczas aktualizacji!']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(CategoryRequest $request)
|
||||||
|
{
|
||||||
|
$validate = $request->validated();
|
||||||
|
if ($category = $this->categoryRepository->create($validate)) {
|
||||||
|
return redirect()->route('admin.category.update', ['category' => $category])->with('message', 'Utworzono kategorię!');
|
||||||
|
}
|
||||||
|
|
||||||
|
return back()->withError(['message_error', 'Wystąpił błąd podczas tworzenia!']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(): View
|
||||||
|
{
|
||||||
|
return view('dashboard.categories.create');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(Category $category): View
|
||||||
|
{
|
||||||
|
return view('dashboard.categories.edit', compact('category'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(Category $category): View
|
||||||
|
{
|
||||||
|
return view('dashboard.categories.delete', compact('category'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(Category $category): RedirectResponse
|
||||||
|
{
|
||||||
|
$name = $category->name;
|
||||||
|
$category->delete();
|
||||||
|
|
||||||
|
return redirect()->route('admin.home')->with('message', 'Usunięto kategorię "'. $name .'"');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
65
app/Http/Controllers/Dashboard/ProjectController.php
Normal file
65
app/Http/Controllers/Dashboard/ProjectController.php
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Dashboard;
|
||||||
|
|
||||||
|
use App\Http\Requests\ProjectRequest;
|
||||||
|
use App\Models\Project;
|
||||||
|
use App\Repository\Interfaces\ProjectRepository;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
class ProjectController
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private ProjectRepository $projectRepository
|
||||||
|
) {
|
||||||
|
$this->projectRepository->auth = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(Project $project): View
|
||||||
|
{
|
||||||
|
return view('dashboard.projects.edit', compact('project'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(ProjectRequest $request, Project $project): RedirectResponse
|
||||||
|
{
|
||||||
|
$validated = $request->validated();
|
||||||
|
if ($this->projectRepository->update($project, $validated)) {
|
||||||
|
return back()->with('message', 'Zaktualizowano projekt!');
|
||||||
|
}
|
||||||
|
|
||||||
|
return back()->withError(['message_error', 'Wystąpił błąd podczas aktualizacji!']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(): View
|
||||||
|
{
|
||||||
|
return view('dashboard.projects.create');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(ProjectRequest $request): RedirectResponse
|
||||||
|
{
|
||||||
|
$validated = $request->validated();
|
||||||
|
if ($project = $this->projectRepository->create($validated)) {
|
||||||
|
return redirect()
|
||||||
|
->route('admin.project.update', compact('project'))
|
||||||
|
->with('message', 'Utworzono projekt!');
|
||||||
|
}
|
||||||
|
|
||||||
|
return back()->withError(['message_error', 'Wystąpił błąd podczas tworzenia!']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(Project $project): View
|
||||||
|
{
|
||||||
|
return view('dashboard.projects.delete', compact('project'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(Project $project): RedirectResponse
|
||||||
|
{
|
||||||
|
$title = $project->title;
|
||||||
|
$project->delete();
|
||||||
|
return redirect()->route('admin.home')->with('message', 'Usunięto projekt "'. $title .'"');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
52
app/Http/Kernel.php
Normal file
52
app/Http/Kernel.php
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http;
|
||||||
|
|
||||||
|
use App\Http\Middleware\Core;
|
||||||
|
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||||
|
|
||||||
|
class Kernel extends HttpKernel
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $middleware = [
|
||||||
|
\App\Http\Middleware\TrustProxies::class,
|
||||||
|
\Illuminate\Http\Middleware\HandleCors::class,
|
||||||
|
\Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
||||||
|
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||||
|
\App\Http\Middleware\TrimStrings::class,
|
||||||
|
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||||
|
Core::class
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $middlewareGroups = [
|
||||||
|
'web' => [
|
||||||
|
\Illuminate\Cookie\Middleware\EncryptCookies::class,
|
||||||
|
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||||
|
\Illuminate\Session\Middleware\StartSession::class,
|
||||||
|
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||||
|
\Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::class,
|
||||||
|
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
'api' => [
|
||||||
|
'throttle:api',
|
||||||
|
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $routeMiddleware = [
|
||||||
|
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||||
|
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||||
|
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||||
|
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
||||||
|
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
||||||
|
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||||
|
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
||||||
|
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
||||||
|
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||||
|
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
19
app/Http/Middleware/Authenticate.php
Normal file
19
app/Http/Middleware/Authenticate.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Auth\Middleware\Authenticate as Middleware;
|
||||||
|
|
||||||
|
class Authenticate extends Middleware
|
||||||
|
{
|
||||||
|
|
||||||
|
protected function redirectTo($request): ?string
|
||||||
|
{
|
||||||
|
if (! $request->expectsJson()) {
|
||||||
|
return route('admin.auth.login');
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
21
app/Http/Middleware/Core.php
Normal file
21
app/Http/Middleware/Core.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class Core
|
||||||
|
{
|
||||||
|
|
||||||
|
public function handle(Request $request, Closure $next): mixed
|
||||||
|
{
|
||||||
|
return $next($request)
|
||||||
|
->header('Access-Control-Allow-Origin', '*')
|
||||||
|
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS')
|
||||||
|
->header('Access-Control-Allow-Headers', 'Content-Type, Authorizations');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
app/Http/Middleware/RedirectIfAuthenticated.php
Normal file
28
app/Http/Middleware/RedirectIfAuthenticated.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Providers\RouteServiceProvider;
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
class RedirectIfAuthenticated
|
||||||
|
{
|
||||||
|
|
||||||
|
public function handle(Request $request, Closure $next, ...$guards): mixed
|
||||||
|
{
|
||||||
|
$guards = empty($guards) ? [null] : $guards;
|
||||||
|
|
||||||
|
foreach ($guards as $guard) {
|
||||||
|
if (Auth::guard($guard)->check()) {
|
||||||
|
return redirect(RouteServiceProvider::HOME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
18
app/Http/Middleware/TrimStrings.php
Normal file
18
app/Http/Middleware/TrimStrings.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
|
||||||
|
|
||||||
|
class TrimStrings extends Middleware
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $except = [
|
||||||
|
'current_password',
|
||||||
|
'password',
|
||||||
|
'password_confirmation',
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
19
app/Http/Middleware/TrustHosts.php
Normal file
19
app/Http/Middleware/TrustHosts.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Http\Middleware\TrustHosts as Middleware;
|
||||||
|
|
||||||
|
class TrustHosts extends Middleware
|
||||||
|
{
|
||||||
|
|
||||||
|
public function hosts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
$this->allSubdomainsOfApplicationUrl(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
19
app/Http/Middleware/TrustProxies.php
Normal file
19
app/Http/Middleware/TrustProxies.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Http\Middleware\TrustProxies as Middleware;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class TrustProxies extends Middleware
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $proxies;
|
||||||
|
protected $headers =
|
||||||
|
Request::HEADER_X_FORWARDED_FOR |
|
||||||
|
Request::HEADER_X_FORWARDED_HOST |
|
||||||
|
Request::HEADER_X_FORWARDED_PORT |
|
||||||
|
Request::HEADER_X_FORWARDED_PROTO |
|
||||||
|
Request::HEADER_X_FORWARDED_AWS_ELB;
|
||||||
|
|
||||||
|
}
|
34
app/Http/Requests/CategoryRequest.php
Normal file
34
app/Http/Requests/CategoryRequest.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class CategoryRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => 'required|string|min:3|max:25',
|
||||||
|
'slug' => 'required|string|min:3|max:25',
|
||||||
|
'priority' => 'required|numeric|min:0|max:10',
|
||||||
|
'default' => 'nullable|in:yes,1,true,on',
|
||||||
|
'visible' => 'nullable|in:yes,1,true,on'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
43
app/Http/Requests/ProjectRequest.php
Normal file
43
app/Http/Requests/ProjectRequest.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class ProjectRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'title' => 'required|string|min:3|max:255',
|
||||||
|
'author' => 'required|string|min:3|max:50',
|
||||||
|
'categories' => 'nullable|string',
|
||||||
|
'release_date' => 'required|date:Y-m-d',
|
||||||
|
'update_date' => 'nullable|date:Y-m-d',
|
||||||
|
|
||||||
|
'image_small' => 'nullable|string',
|
||||||
|
'image_medium' => 'nullable|string',
|
||||||
|
'image_large' => 'nullable|string',
|
||||||
|
|
||||||
|
'project_url' => 'nullable|string',
|
||||||
|
'project_version' => 'nullable|string',
|
||||||
|
'description' => 'nullable|string',
|
||||||
|
'visible' => 'nullable|in:yes,1,true,on'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
19
app/Http/Resources/CategoryCollection.php
Normal file
19
app/Http/Resources/CategoryCollection.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||||
|
|
||||||
|
class CategoryCollection extends ResourceCollection
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource collection into an array.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
|
||||||
|
*/
|
||||||
|
public function toArray($request)
|
||||||
|
{
|
||||||
|
return CategoryResource::collection($this->collection);
|
||||||
|
}
|
||||||
|
}
|
27
app/Http/Resources/CategoryResource.php
Normal file
27
app/Http/Resources/CategoryResource.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class CategoryResource extends JsonResource
|
||||||
|
{
|
||||||
|
|
||||||
|
public static $wrap = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
|
||||||
|
*/
|
||||||
|
public function toArray($request)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->id,
|
||||||
|
'name' => $this->name,
|
||||||
|
'slug' => $this->slug,
|
||||||
|
'default' => $this->default,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
19
app/Http/Resources/ProjectCollection.php
Normal file
19
app/Http/Resources/ProjectCollection.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||||
|
|
||||||
|
class ProjectCollection extends ResourceCollection
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource collection into an array.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
|
||||||
|
*/
|
||||||
|
public function toArray($request)
|
||||||
|
{
|
||||||
|
return ProjectResource::collection($this->collection);
|
||||||
|
}
|
||||||
|
}
|
34
app/Http/Resources/ProjectResource.php
Normal file
34
app/Http/Resources/ProjectResource.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class ProjectResource extends JsonResource
|
||||||
|
{
|
||||||
|
|
||||||
|
public static $wrap = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
|
||||||
|
*/
|
||||||
|
public function toArray($request)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->id,
|
||||||
|
'title' => $this->title,
|
||||||
|
'categories' => $this->categories,
|
||||||
|
'author' => $this->author,
|
||||||
|
'images' => $this->images,
|
||||||
|
'release_date' => $this->release_date,
|
||||||
|
'update_date' => $this->update_date,
|
||||||
|
'project_url' => $this->project_url,
|
||||||
|
'project_version' => $this->project_version,
|
||||||
|
'description' => $this->description,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,78 +1,38 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace KamilCraftApi\App\Models;
|
declare(strict_types=1);
|
||||||
|
|
||||||
use KamilCraftApi\Request\Request;
|
namespace App\Models;
|
||||||
use KamilCraftApi\Response;
|
|
||||||
use stdClass;
|
|
||||||
|
|
||||||
class Category
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property string $name
|
||||||
|
* @property string $slug
|
||||||
|
* @property bool $default
|
||||||
|
* @property bool $visible
|
||||||
|
*/
|
||||||
|
class Category extends Model
|
||||||
{
|
{
|
||||||
const JSON_PATH = ROOT_PATH . 'resources/json';
|
|
||||||
private array $allCategory = [];
|
|
||||||
|
|
||||||
public function __construct(
|
protected $guarded = [];
|
||||||
private Request $request
|
protected $casts = [
|
||||||
) {
|
'id' => 'integer',
|
||||||
$categories = file_get_contents(self::JSON_PATH . '/Categories.json');
|
'name' => 'string',
|
||||||
if ( $category = json_decode($categories) ) {
|
'slug' => 'string',
|
||||||
$this->allCategory = $category;
|
'priority' => 'integer',
|
||||||
} else {
|
'default' => 'boolean',
|
||||||
$this->parseError();
|
'visible' => 'boolean'
|
||||||
}
|
];
|
||||||
}
|
|
||||||
|
|
||||||
public function getCategoryWhereName(string $slug): object|bool
|
public function scopeVisibled(Builder $builder): Builder
|
||||||
{
|
{
|
||||||
if ( ( $key = array_search($slug, array_column($this->allCategory, 'slug') ) ) !== false ) {
|
return $builder->where(function (Builder $query) {
|
||||||
$category = $this->allCategory[$key];
|
$query->where('visible', true)
|
||||||
$category->default = $category->default ?? false;
|
->orWhere('default', true);
|
||||||
$category->visible = $category->visible ?? true;
|
});
|
||||||
return $category;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCategory(int $id): object|bool
|
|
||||||
{
|
|
||||||
if ( ( $key = array_search($id, array_column($this->allCategory, 'id') ) ) !== false ) {
|
|
||||||
$category = $this->allCategory[$key];
|
|
||||||
$category->default = $category->default ?? false;
|
|
||||||
$category->visible = $category->visible ?? true;
|
|
||||||
return $category;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function parseError(): void
|
|
||||||
{
|
|
||||||
if ( $this->request->getContentType() === 'application/json' ) {
|
|
||||||
(new Response())->json((object)[
|
|
||||||
'message' => 'Server error'
|
|
||||||
], 500)->render();
|
|
||||||
} else {
|
|
||||||
(new Response())(
|
|
||||||
file_get_contents(ROOT_PATH . '/errors/error500.html'),
|
|
||||||
500
|
|
||||||
)->render();
|
|
||||||
}
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __invoke(): array
|
|
||||||
{
|
|
||||||
$tmp_categories = [];
|
|
||||||
foreach ($this->allCategory as $category) {
|
|
||||||
$tmp_category = new stdClass;
|
|
||||||
$tmp_category->id = $category->id;
|
|
||||||
$tmp_category->name = $category->name;
|
|
||||||
$tmp_category->slug = $category->slug;
|
|
||||||
$tmp_category->default = $category->default ?? false;
|
|
||||||
$tmp_category->visible = $category->visible ?? true;
|
|
||||||
|
|
||||||
$tmp_categories[] = $tmp_category;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $tmp_categories;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,72 +1,70 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace KamilCraftApi\App\Models;
|
declare(strict_types=1);
|
||||||
|
|
||||||
use stdClass;
|
namespace App\Models;
|
||||||
|
|
||||||
class Project
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property string $title
|
||||||
|
* @property array $categories
|
||||||
|
* @property string $author
|
||||||
|
* @property array $images
|
||||||
|
* @property Carbon $release_date
|
||||||
|
* @property Carbon $update_date
|
||||||
|
* @property string $project_url
|
||||||
|
* @property string $project_version
|
||||||
|
* @property string $description
|
||||||
|
*/
|
||||||
|
class Project extends Model
|
||||||
{
|
{
|
||||||
const JSON_PATH = ROOT_PATH . 'resources/json';
|
|
||||||
const SHORT_PROJECT = [
|
protected $dateFormat = 'Y-m-d';
|
||||||
'id',
|
protected $guarded = [];
|
||||||
'title',
|
protected $casts = [
|
||||||
'image',
|
'id' => 'integer',
|
||||||
'categories',
|
'title' => 'string',
|
||||||
'version'
|
'categories' => 'array',
|
||||||
|
'author' => 'string',
|
||||||
|
'images' => 'array',
|
||||||
|
'release_date' => 'datetime:Y-m-d',
|
||||||
|
'update_date' => 'datetime:Y-m-d',
|
||||||
|
'project_url' => 'string',
|
||||||
|
'project_version' => 'string',
|
||||||
|
'description' => 'string',
|
||||||
|
'visible' => 'boolean'
|
||||||
];
|
];
|
||||||
private array $allProjects = [];
|
|
||||||
|
|
||||||
public function __construct()
|
public function getReleaseDateAttribute($value): String
|
||||||
{
|
{
|
||||||
$projects = file_get_contents(self::JSON_PATH . '/Projects.json');
|
return Carbon::parse($value)->format('Y-m-d');
|
||||||
if ( $projects = json_decode($projects) ) {
|
|
||||||
$this->allProjects = $projects;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getProject(int $id): object|bool
|
public function setReleaseDateAttribute($value): void
|
||||||
{
|
{
|
||||||
if ( ( $key = array_search($id, array_column($this->allProjects, 'id')) ) !== false ) {
|
$this->attributes['release_date'] = $value;
|
||||||
return $this->allProjects[$key];
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getProjectWhereCategory(string $category): array
|
public function getUpdateDateAttribute($value): String|null
|
||||||
{
|
{
|
||||||
$listWhereCategory = [];
|
return Carbon::parse($value)->format('Y-m-d');
|
||||||
foreach ( array_column($this->allProjects, 'categories') as $key => $value ) {
|
|
||||||
if ( in_array($category, $value) ) {
|
|
||||||
$listWhereCategory[] = $this->shortProjectSchema($this->allProjects[$key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $listWhereCategory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function shortProjectSchema(object $project): object
|
public function setUpdateDateAttribute($value): void
|
||||||
{
|
{
|
||||||
$tmp_project = new stdClass;
|
if (!is_null($value))
|
||||||
foreach ($project as $key => $value) {
|
$this->attributes['update_date'] = $value;
|
||||||
if ( in_array($key, self::SHORT_PROJECT) ) {
|
else
|
||||||
$tmp_project->{$key} = $value;
|
$this->attributes['update_date'] = null;
|
||||||
}
|
|
||||||
}
|
|
||||||
$tmp_project->short_description = substr(
|
|
||||||
explode("\n", $project->description)[0],
|
|
||||||
0,
|
|
||||||
255
|
|
||||||
);
|
|
||||||
|
|
||||||
return $tmp_project;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __invoke(): array
|
public function scopeVisibled(Builder $builder): Builder
|
||||||
{
|
{
|
||||||
$arr_map = [];
|
return $builder->where('visible', true);
|
||||||
foreach ($this->allProjects as $project) {
|
|
||||||
$arr_map[] = $this->shortProjectSchema($project);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $arr_map;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
31
app/Models/User.php
Normal file
31
app/Models/User.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
|
use Illuminate\Notifications\Notifiable;
|
||||||
|
|
||||||
|
class User extends Authenticatable
|
||||||
|
{
|
||||||
|
|
||||||
|
use HasFactory, Notifiable;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'email',
|
||||||
|
'password',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $hidden = [
|
||||||
|
'password',
|
||||||
|
'remember_token',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'email_verified_at' => 'datetime',
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
10
app/Providers/AppServiceProvider.php
Normal file
10
app/Providers/AppServiceProvider.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
|
class AppServiceProvider extends ServiceProvider
|
||||||
|
{}
|
17
app/Providers/AuthServiceProvider.php
Normal file
17
app/Providers/AuthServiceProvider.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||||
|
|
||||||
|
class AuthServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
$this->registerPolicies();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
app/Providers/CategoryServiceProvider.php
Normal file
20
app/Providers/CategoryServiceProvider.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use App\Repository\CategoryRepository;
|
||||||
|
use App\Repository\Interfaces\CategoryRepository as CategoryRepositoryInterface;
|
||||||
|
|
||||||
|
class CategoryServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
$this->app
|
||||||
|
->bind(CategoryRepositoryInterface::class, CategoryRepository::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
19
app/Providers/ProjectServiceProvider.php
Normal file
19
app/Providers/ProjectServiceProvider.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use App\Repository\Interfaces\ProjectRepository as ProjectRepositoryInterface;
|
||||||
|
use App\Repository\ProjectRepository;
|
||||||
|
|
||||||
|
class ProjectServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
$this->app->bind(ProjectRepositoryInterface::class, ProjectRepository::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
41
app/Providers/RouteServiceProvider.php
Normal file
41
app/Providers/RouteServiceProvider.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Cache\RateLimiting\Limit;
|
||||||
|
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\RateLimiter;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
class RouteServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
|
||||||
|
public const HOME = '/';
|
||||||
|
protected $namespace = 'App\\Http\\Controllers';
|
||||||
|
|
||||||
|
public function boot(): void
|
||||||
|
{
|
||||||
|
$this->configureRateLimiting();
|
||||||
|
|
||||||
|
$this->routes(function () {
|
||||||
|
Route::prefix('v1')
|
||||||
|
->middleware('api')
|
||||||
|
->namespace($this->namespace . '\\Api')
|
||||||
|
->group(base_path('routes/api.php'));
|
||||||
|
|
||||||
|
Route::prefix('dashboard')
|
||||||
|
->middleware('web')
|
||||||
|
->namespace($this->namespace)
|
||||||
|
->group(base_path('routes/web.php'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configureRateLimiting()
|
||||||
|
{
|
||||||
|
RateLimiter::for('api', function (Request $request) {
|
||||||
|
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
104
app/Repository/CategoryRepository.php
Normal file
104
app/Repository/CategoryRepository.php
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Repository;
|
||||||
|
|
||||||
|
use App\Http\Resources\CategoryCollection;
|
||||||
|
use App\Http\Resources\CategoryResource;
|
||||||
|
use App\Models\Category;
|
||||||
|
use App\Repository\Interfaces\CategoryRepository as CategoryRepositoryInterface;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
class CategoryRepository implements CategoryRepositoryInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
public bool $auth = false;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private Category $category
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function all(): Collection
|
||||||
|
{
|
||||||
|
$categories = $this->category
|
||||||
|
->query()
|
||||||
|
->orderby('priority', 'ASC')
|
||||||
|
->orderby('name', 'ASC');
|
||||||
|
|
||||||
|
if (!$this->auth)
|
||||||
|
$categories->visibled();
|
||||||
|
|
||||||
|
return (new CategoryCollection($categories->get()))->collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(string $slug): CategoryResource
|
||||||
|
{
|
||||||
|
$category = $this->category
|
||||||
|
->query()
|
||||||
|
->where('slug', $slug)
|
||||||
|
->firstOrFail();
|
||||||
|
|
||||||
|
if (!$this->auth)
|
||||||
|
$category->visibled();
|
||||||
|
|
||||||
|
return new CategoryResource($category);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(Category $category, array $data = []): bool
|
||||||
|
{
|
||||||
|
$data = $this->parseToArray($data);
|
||||||
|
if (!$category->default && isset($data['default']) && $data['default'] === true)
|
||||||
|
$this->unsetDefault();
|
||||||
|
|
||||||
|
return $category
|
||||||
|
->update($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(array $data = []): Category
|
||||||
|
{
|
||||||
|
$data = $this->parseToArray($data);
|
||||||
|
if (isset($data['default']) && $data['default'] === true)
|
||||||
|
$this->unsetDefault();
|
||||||
|
|
||||||
|
return $this->category
|
||||||
|
->query()
|
||||||
|
->create($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function unsetDefault(): void
|
||||||
|
{
|
||||||
|
$this->category
|
||||||
|
->query()
|
||||||
|
->where('default', true)
|
||||||
|
->first()?->update(['default' => false]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseToArray(array $data = []): array
|
||||||
|
{
|
||||||
|
$toSave = [];
|
||||||
|
|
||||||
|
if (isset($data['name']) && !empty($data['name']))
|
||||||
|
$toSave['name'] = $data['name'];
|
||||||
|
if (isset($data['slug']) && !empty($data['slug']))
|
||||||
|
$toSave['slug'] = $data['slug'];
|
||||||
|
if (isset($data['priority']) && !is_integer($data['priority']))
|
||||||
|
$toSave['priority'] = (int)$data['priority'];
|
||||||
|
|
||||||
|
if (
|
||||||
|
isset($data['default']) &&
|
||||||
|
in_array($data['default'], ['yes', 'on', 1, true])
|
||||||
|
) $toSave['default'] = true;
|
||||||
|
else $toSave['default'] = false;
|
||||||
|
|
||||||
|
if (
|
||||||
|
(isset($toSave['default']) && $toSave['default'] === true) ||
|
||||||
|
(isset($data['visible']) &&
|
||||||
|
in_array($data['visible'], ['yes', 'on', 1, true]))
|
||||||
|
) $toSave['visible'] = true;
|
||||||
|
else $toSave['visible'] = false;
|
||||||
|
|
||||||
|
return $toSave;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
19
app/Repository/Interfaces/CategoryRepository.php
Normal file
19
app/Repository/Interfaces/CategoryRepository.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Repository\Interfaces;
|
||||||
|
|
||||||
|
use App\Http\Resources\CategoryResource;
|
||||||
|
use App\Models\Category;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
interface CategoryRepository
|
||||||
|
{
|
||||||
|
|
||||||
|
public function all(): Collection;
|
||||||
|
public function get(string $slug): CategoryResource;
|
||||||
|
public function update(Category $category, array $data = []): bool;
|
||||||
|
public function create(array $data = []): Category;
|
||||||
|
|
||||||
|
}
|
19
app/Repository/Interfaces/ProjectRepository.php
Normal file
19
app/Repository/Interfaces/ProjectRepository.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Repository\Interfaces;
|
||||||
|
|
||||||
|
use App\Http\Resources\ProjectResource;
|
||||||
|
use App\Models\Project;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
interface ProjectRepository
|
||||||
|
{
|
||||||
|
|
||||||
|
public function all(array $filters = []): Collection;
|
||||||
|
public function get(int $id): ProjectResource;
|
||||||
|
public function update(Project $project, array $data = []): bool;
|
||||||
|
public function create(array $data = []): Project;
|
||||||
|
|
||||||
|
}
|
116
app/Repository/ProjectRepository.php
Normal file
116
app/Repository/ProjectRepository.php
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Repository;
|
||||||
|
|
||||||
|
use App\Http\Resources\ProjectCollection;
|
||||||
|
use App\Http\Resources\ProjectResource;
|
||||||
|
use App\Models\Project;
|
||||||
|
use App\Repository\Interfaces\ProjectRepository as ProjectRepositoryInterface;
|
||||||
|
use Illuminate\Database\Query\Builder;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
class ProjectRepository implements ProjectRepositoryInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
public bool $auth = false;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private Project $project
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function all(array $filters = []): Collection
|
||||||
|
{
|
||||||
|
$project = $this->project
|
||||||
|
->query()
|
||||||
|
->orderByDesc('release_date');
|
||||||
|
|
||||||
|
foreach ($filters as $filter_name => $filter_value) {
|
||||||
|
if ($filter_name === 'category' && $filter_value !== 'all')
|
||||||
|
$project->where('categories', 'like', '%"'. $filter_value .'"%');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->auth)
|
||||||
|
$project->visibled();
|
||||||
|
|
||||||
|
return (new ProjectCollection($project->get()))->collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(int $id): ProjectResource
|
||||||
|
{
|
||||||
|
$project = $this->project
|
||||||
|
->query();
|
||||||
|
|
||||||
|
if (!$this->auth)
|
||||||
|
$project->visibled();
|
||||||
|
|
||||||
|
return new ProjectResource($project->findOrFail($id));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(Project $project, array $data = []): bool
|
||||||
|
{
|
||||||
|
$data = $this->parseToArray($data);
|
||||||
|
|
||||||
|
return $project
|
||||||
|
->update($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(array $data = []): Project
|
||||||
|
{
|
||||||
|
$data = $this->parseToArray($data);
|
||||||
|
|
||||||
|
return $this->project
|
||||||
|
->query()
|
||||||
|
->create($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseToArray(array $data = []): array
|
||||||
|
{
|
||||||
|
$toSave = [];
|
||||||
|
|
||||||
|
if (isset($data['title']))
|
||||||
|
$toSave['title'] = $data['title'];
|
||||||
|
|
||||||
|
if (isset($data['author']))
|
||||||
|
$toSave['author'] = $data['author'];
|
||||||
|
|
||||||
|
$toSave['images']['small'] = $data['image_small'] ?? '';
|
||||||
|
$toSave['images']['medium'] = $data['image_medium'] ?? '';
|
||||||
|
$toSave['images']['large'] = $data['image_large'] ?? '';
|
||||||
|
|
||||||
|
if (isset($data['release_date']))
|
||||||
|
$toSave['release_date'] = $data['release_date'];
|
||||||
|
|
||||||
|
if (isset($data['project_url']))
|
||||||
|
$toSave['project_url'] = $data['project_url'];
|
||||||
|
|
||||||
|
if (isset($data['project_version']))
|
||||||
|
$toSave['project_version'] = $data['project_version'];
|
||||||
|
|
||||||
|
if (isset($data['description']))
|
||||||
|
$toSave['description'] = $data['description'];
|
||||||
|
|
||||||
|
if (isset($data['categories']) && is_array($data['categories']))
|
||||||
|
$toSave['categories'] = $data['categories'];
|
||||||
|
else if (isset($data['categories']) && !empty($data['categories']))
|
||||||
|
$toSave['categories'] = explode(',', str_replace(', ', ',', $data['categories']));
|
||||||
|
|
||||||
|
if (isset($data['images']) && is_array($data['images']))
|
||||||
|
$toSave['images'] = $data['images'];
|
||||||
|
|
||||||
|
if (isset($data['update_date']) && !empty($data['update_date']))
|
||||||
|
$toSave['update_date'] = $data['update_date'];
|
||||||
|
else
|
||||||
|
$toSave['update_date'] = null;
|
||||||
|
|
||||||
|
if (
|
||||||
|
isset($data['visible']) &&
|
||||||
|
in_array($data['visible'], ['yes', 'on', 1, true])
|
||||||
|
) $toSave['visible'] = true;
|
||||||
|
else $toSave['visible'] = false;
|
||||||
|
|
||||||
|
return $toSave;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
53
artisan
Normal file
53
artisan
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
define('LARAVEL_START', microtime(true));
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Register The Auto Loader
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Composer provides a convenient, automatically generated class loader
|
||||||
|
| for our application. We just need to utilize it! We'll require it
|
||||||
|
| into the script here so that we do not have to worry about the
|
||||||
|
| loading of any of our classes manually. It's great to relax.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
require __DIR__.'/vendor/autoload.php';
|
||||||
|
|
||||||
|
$app = require_once __DIR__.'/bootstrap/app.php';
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Run The Artisan Application
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| When we run the console application, the current CLI command will be
|
||||||
|
| executed in this console and the response sent back to a terminal
|
||||||
|
| or another output device for the developers. Here goes nothing!
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
|
||||||
|
|
||||||
|
$status = $kernel->handle(
|
||||||
|
$input = new Symfony\Component\Console\Input\ArgvInput,
|
||||||
|
new Symfony\Component\Console\Output\ConsoleOutput
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Shutdown The Application
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Once Artisan has finished running, we will fire off the shutdown events
|
||||||
|
| so that any final work may be done by the application before we shut
|
||||||
|
| down the process. This is the last thing to happen to the request.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
$kernel->terminate($input, $status);
|
||||||
|
|
||||||
|
exit($status);
|
55
bootstrap/app.php
Normal file
55
bootstrap/app.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Create The Application
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The first thing we will do is create a new Laravel application instance
|
||||||
|
| which serves as the "glue" for all the components of Laravel, and is
|
||||||
|
| the IoC container for the system binding all of the various parts.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
$app = new Illuminate\Foundation\Application(
|
||||||
|
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Bind Important Interfaces
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Next, we need to bind some important interfaces into the container so
|
||||||
|
| we will be able to resolve them when needed. The kernels serve the
|
||||||
|
| incoming requests to this application from both the web and CLI.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
$app->singleton(
|
||||||
|
Illuminate\Contracts\Http\Kernel::class,
|
||||||
|
App\Http\Kernel::class
|
||||||
|
);
|
||||||
|
|
||||||
|
$app->singleton(
|
||||||
|
Illuminate\Contracts\Console\Kernel::class,
|
||||||
|
App\Console\Kernel::class
|
||||||
|
);
|
||||||
|
|
||||||
|
$app->singleton(
|
||||||
|
Illuminate\Contracts\Debug\ExceptionHandler::class,
|
||||||
|
App\Exceptions\Handler::class
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Return The Application
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This script returns the application instance. The instance is given to
|
||||||
|
| the calling script so we can separate the building of the instances
|
||||||
|
| from the actual running of the application and sending responses.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
return $app;
|
2
bootstrap/cache/.gitignore
vendored
Normal file
2
bootstrap/cache/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
@ -1,25 +1,64 @@
|
|||||||
{
|
{
|
||||||
"name": "kamilniemczycki/kamilcraft-api",
|
"name": "kamilniemczycki/kamilcraft-api",
|
||||||
"description": "Api for kamilcraft.com",
|
"type": "project",
|
||||||
|
"description": "The API portfolio of projects.",
|
||||||
"keywords": ["kamilcraft", "api"],
|
"keywords": ["kamilcraft", "api"],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "project",
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Kamil Niemczycki",
|
|
||||||
"email": "contact@kamilcraft.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"minimum-stability": "dev",
|
|
||||||
"prefer-stable": true,
|
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.0",
|
"php": "^8.1",
|
||||||
"symfony/dotenv": "5.3.7"
|
"guzzlehttp/guzzle": "^7.2",
|
||||||
|
"laravel/framework": "^9.19",
|
||||||
|
"laravel/tinker": "^2.7"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"barryvdh/laravel-debugbar": "^3.6",
|
||||||
|
"fakerphp/faker": "^1.9.1",
|
||||||
|
"laravel/pint": "^1.0",
|
||||||
|
"mockery/mockery": "^1.4.4",
|
||||||
|
"nunomaduro/collision": "^6.1",
|
||||||
|
"phpunit/phpunit": "^9.5.10",
|
||||||
|
"spatie/laravel-ignition": "^1.0"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"KamilCraftApi\\": "src/",
|
"App\\": "app/",
|
||||||
"KamilCraftApi\\App\\": "app/"
|
"Database\\Factories\\": "database/factories/",
|
||||||
|
"Database\\Seeders\\": "database/seeders/"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"Tests\\": "tests/"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"post-autoload-dump": [
|
||||||
|
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||||
|
"@php artisan package:discover --ansi"
|
||||||
|
],
|
||||||
|
"post-update-cmd": [
|
||||||
|
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
|
||||||
|
],
|
||||||
|
"post-root-package-install": [
|
||||||
|
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
||||||
|
],
|
||||||
|
"post-create-project-cmd": [
|
||||||
|
"@php artisan key:generate --ansi"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"dont-discover": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"optimize-autoloader": true,
|
||||||
|
"preferred-install": "dist",
|
||||||
|
"sort-packages": true,
|
||||||
|
"allow-plugins": {
|
||||||
|
"pestphp/pest-plugin": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"prefer-stable": true
|
||||||
}
|
}
|
||||||
|
7796
composer.lock
generated
7796
composer.lock
generated
File diff suppressed because it is too large
Load Diff
51
config/app.php
Normal file
51
config/app.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Facade;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'name' => env('APP_NAME', 'KamilCraft API'),
|
||||||
|
'env' => env('APP_ENV', 'production'),
|
||||||
|
'debug' => (bool) env('APP_DEBUG', false),
|
||||||
|
'url' => env('APP_URL', 'http://localhost'),
|
||||||
|
'asset_url' => env('ASSET_URL'),
|
||||||
|
'timezone' => 'UTC',
|
||||||
|
'locale' => 'pl',
|
||||||
|
'fallback_locale' => 'en',
|
||||||
|
'faker_locale' => 'en_US',
|
||||||
|
'key' => env('APP_KEY'),
|
||||||
|
'cipher' => 'AES-256-CBC',
|
||||||
|
'maintenance' => [
|
||||||
|
'driver' => 'file',
|
||||||
|
],
|
||||||
|
'providers' => [
|
||||||
|
Illuminate\Auth\AuthServiceProvider::class,
|
||||||
|
Illuminate\Bus\BusServiceProvider::class,
|
||||||
|
Illuminate\Cache\CacheServiceProvider::class,
|
||||||
|
Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
|
||||||
|
Illuminate\Cookie\CookieServiceProvider::class,
|
||||||
|
Illuminate\Database\DatabaseServiceProvider::class,
|
||||||
|
Illuminate\Encryption\EncryptionServiceProvider::class,
|
||||||
|
Illuminate\Filesystem\FilesystemServiceProvider::class,
|
||||||
|
Illuminate\Foundation\Providers\FoundationServiceProvider::class,
|
||||||
|
Illuminate\Hashing\HashServiceProvider::class,
|
||||||
|
Illuminate\Notifications\NotificationServiceProvider::class,
|
||||||
|
Illuminate\Pagination\PaginationServiceProvider::class,
|
||||||
|
Illuminate\Pipeline\PipelineServiceProvider::class,
|
||||||
|
Illuminate\Queue\QueueServiceProvider::class,
|
||||||
|
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
|
||||||
|
Illuminate\Session\SessionServiceProvider::class,
|
||||||
|
Illuminate\Translation\TranslationServiceProvider::class,
|
||||||
|
Illuminate\Validation\ValidationServiceProvider::class,
|
||||||
|
Illuminate\View\ViewServiceProvider::class,
|
||||||
|
|
||||||
|
App\Providers\AppServiceProvider::class,
|
||||||
|
App\Providers\AuthServiceProvider::class,
|
||||||
|
App\Providers\RouteServiceProvider::class,
|
||||||
|
|
||||||
|
App\Providers\CategoryServiceProvider::class,
|
||||||
|
App\Providers\ProjectServiceProvider::class,
|
||||||
|
],
|
||||||
|
'aliases' => Facade::defaultAliases()->merge([])->toArray()
|
||||||
|
];
|
31
config/auth.php
Normal file
31
config/auth.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'defaults' => [
|
||||||
|
'guard' => 'web',
|
||||||
|
'passwords' => 'users',
|
||||||
|
],
|
||||||
|
'guards' => [
|
||||||
|
'web' => [
|
||||||
|
'driver' => 'session',
|
||||||
|
'provider' => 'users',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'providers' => [
|
||||||
|
'users' => [
|
||||||
|
'driver' => 'eloquent',
|
||||||
|
'model' => App\Models\User::class,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'passwords' => [
|
||||||
|
'users' => [
|
||||||
|
'provider' => 'users',
|
||||||
|
'table' => 'password_resets',
|
||||||
|
'expire' => 60,
|
||||||
|
'throttle' => 60,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'password_timeout' => 10800,
|
||||||
|
];
|
47
config/cache.php
Normal file
47
config/cache.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'default' => env('CACHE_DRIVER', 'file'),
|
||||||
|
'stores' => [
|
||||||
|
'apc' => [
|
||||||
|
'driver' => 'apc',
|
||||||
|
],
|
||||||
|
'array' => [
|
||||||
|
'driver' => 'array',
|
||||||
|
'serialize' => false,
|
||||||
|
],
|
||||||
|
'database' => [
|
||||||
|
'driver' => 'database',
|
||||||
|
'table' => 'cache',
|
||||||
|
'connection' => null,
|
||||||
|
'lock_connection' => null,
|
||||||
|
],
|
||||||
|
'file' => [
|
||||||
|
'driver' => 'file',
|
||||||
|
'path' => storage_path('framework/cache/data'),
|
||||||
|
],
|
||||||
|
'memcached' => [
|
||||||
|
'driver' => 'memcached',
|
||||||
|
'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
|
||||||
|
'sasl' => [
|
||||||
|
env('MEMCACHED_USERNAME'),
|
||||||
|
env('MEMCACHED_PASSWORD'),
|
||||||
|
],
|
||||||
|
'options' => [
|
||||||
|
// Memcached::OPT_CONNECT_TIMEOUT => 2000,
|
||||||
|
],
|
||||||
|
'servers' => [
|
||||||
|
[
|
||||||
|
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
|
||||||
|
'port' => env('MEMCACHED_PORT', 11211),
|
||||||
|
'weight' => 100,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'KamilCraftAPI'), '_').'_cache_'),
|
||||||
|
];
|
14
config/cors.php
Normal file
14
config/cors.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'paths' => ['api/*', 'sanctum/csrf-cookie'],
|
||||||
|
'allowed_methods' => ['*'],
|
||||||
|
'allowed_origins' => ['*'],
|
||||||
|
'allowed_origins_patterns' => [],
|
||||||
|
'allowed_headers' => ['*'],
|
||||||
|
'exposed_headers' => [],
|
||||||
|
'max_age' => 0,
|
||||||
|
'supports_credentials' => false,
|
||||||
|
];
|
37
config/database.php
Normal file
37
config/database.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'default' => env('DB_CONNECTION', 'mysql'),
|
||||||
|
'connections' => [
|
||||||
|
'sqlite' => [
|
||||||
|
'driver' => 'sqlite',
|
||||||
|
'url' => env('DATABASE_URL'),
|
||||||
|
'database' => env('DB_DATABASE', database_path('database.sqlite')),
|
||||||
|
'prefix' => '',
|
||||||
|
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
|
||||||
|
],
|
||||||
|
'mysql' => [
|
||||||
|
'driver' => 'mysql',
|
||||||
|
'url' => env('DATABASE_URL'),
|
||||||
|
'host' => env('DB_HOST', '127.0.0.1'),
|
||||||
|
'port' => env('DB_PORT', '3306'),
|
||||||
|
'database' => env('DB_DATABASE', 'forge'),
|
||||||
|
'username' => env('DB_USERNAME', 'forge'),
|
||||||
|
'password' => env('DB_PASSWORD', ''),
|
||||||
|
'unix_socket' => env('DB_SOCKET', ''),
|
||||||
|
'charset' => 'utf8mb4',
|
||||||
|
'collation' => 'utf8mb4_unicode_ci',
|
||||||
|
'prefix' => '',
|
||||||
|
'prefix_indexes' => true,
|
||||||
|
'search_path' => 'public',
|
||||||
|
'strict' => true,
|
||||||
|
'engine' => null,
|
||||||
|
'options' => extension_loaded('pdo_mysql') ? array_filter([
|
||||||
|
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
|
||||||
|
]) : [],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'migrations' => 'migrations',
|
||||||
|
];
|
92
config/debugbar.php
Normal file
92
config/debugbar.php
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'enabled' => env('DEBUGBAR_ENABLED', null),
|
||||||
|
'except' => [
|
||||||
|
'telescope*',
|
||||||
|
'horizon*',
|
||||||
|
],
|
||||||
|
'storage' => [
|
||||||
|
'enabled' => true,
|
||||||
|
'driver' => 'file', // redis, file, pdo, socket, custom
|
||||||
|
'path' => storage_path('debugbar'), // For file driver
|
||||||
|
'connection' => null, // Leave null for default connection (Redis/PDO)
|
||||||
|
'provider' => '', // Instance of StorageInterface for custom driver
|
||||||
|
'hostname' => '127.0.0.1', // Hostname to use with the "socket" driver
|
||||||
|
'port' => 2304, // Port to use with the "socket" driver
|
||||||
|
],
|
||||||
|
'editor' => env('DEBUGBAR_EDITOR', 'phpstorm'),
|
||||||
|
'remote_sites_path' => env('DEBUGBAR_REMOTE_SITES_PATH', ''),
|
||||||
|
'local_sites_path' => env('DEBUGBAR_LOCAL_SITES_PATH', ''),
|
||||||
|
'include_vendors' => true,
|
||||||
|
'capture_ajax' => true,
|
||||||
|
'add_ajax_timing' => false,
|
||||||
|
'error_handler' => false,
|
||||||
|
'clockwork' => false,
|
||||||
|
'collectors' => [
|
||||||
|
'phpinfo' => true, // Php version
|
||||||
|
'messages' => true, // Messages
|
||||||
|
'time' => true, // Time Datalogger
|
||||||
|
'memory' => true, // Memory usage
|
||||||
|
'exceptions' => true, // Exception displayer
|
||||||
|
'log' => true, // Logs from Monolog (merged in messages if enabled)
|
||||||
|
'db' => true, // Show database (PDO) queries and bindings
|
||||||
|
'views' => true, // Views with their data
|
||||||
|
'route' => true, // Current route information
|
||||||
|
'auth' => false, // Display Laravel authentication status
|
||||||
|
'gate' => true, // Display Laravel Gate checks
|
||||||
|
'session' => true, // Display session data
|
||||||
|
'symfony_request' => true, // Only one can be enabled..
|
||||||
|
'mail' => true, // Catch mail messages
|
||||||
|
'laravel' => false, // Laravel version and environment
|
||||||
|
'events' => false, // All events fired
|
||||||
|
'default_request' => false, // Regular or special Symfony request logger
|
||||||
|
'logs' => false, // Add the latest log messages
|
||||||
|
'files' => false, // Show the included files
|
||||||
|
'config' => false, // Display config settings
|
||||||
|
'cache' => false, // Display cache events
|
||||||
|
'models' => true, // Display models
|
||||||
|
'livewire' => true, // Display Livewire (when available)
|
||||||
|
],
|
||||||
|
'options' => [
|
||||||
|
'auth' => [
|
||||||
|
'show_name' => true, // Also show the users name/email in the debugbar
|
||||||
|
],
|
||||||
|
'db' => [
|
||||||
|
'with_params' => true, // Render SQL with the parameters substituted
|
||||||
|
'backtrace' => true, // Use a backtrace to find the origin of the query in your files.
|
||||||
|
'backtrace_exclude_paths' => [], // Paths to exclude from backtrace. (in addition to defaults)
|
||||||
|
'timeline' => false, // Add the queries to the timeline
|
||||||
|
'duration_background' => true, // Show shaded background on each query relative to how long it took to execute.
|
||||||
|
'explain' => [ // Show EXPLAIN output on queries
|
||||||
|
'enabled' => false,
|
||||||
|
'types' => ['SELECT'], // Deprecated setting, is always only SELECT
|
||||||
|
],
|
||||||
|
'hints' => false, // Show hints for common mistakes
|
||||||
|
'show_copy' => false, // Show copy button next to the query
|
||||||
|
],
|
||||||
|
'mail' => [
|
||||||
|
'full_log' => false,
|
||||||
|
],
|
||||||
|
'views' => [
|
||||||
|
'timeline' => false, // Add the views to the timeline (Experimental)
|
||||||
|
'data' => false, //Note: Can slow down the application, because the data can be quite large..
|
||||||
|
],
|
||||||
|
'route' => [
|
||||||
|
'label' => true, // show complete route on bar
|
||||||
|
],
|
||||||
|
'logs' => [
|
||||||
|
'file' => null,
|
||||||
|
],
|
||||||
|
'cache' => [
|
||||||
|
'values' => true, // collect cache values
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'inject' => true,
|
||||||
|
'route_prefix' => '_debugbar',
|
||||||
|
'route_domain' => null,
|
||||||
|
'theme' => env('DEBUGBAR_THEME', 'auto'),
|
||||||
|
'debug_backtrace_limit' => 50,
|
||||||
|
];
|
26
config/filesystems.php
Normal file
26
config/filesystems.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'default' => env('FILESYSTEM_DRIVER', 'local'),
|
||||||
|
'disks' => [
|
||||||
|
'local' => [
|
||||||
|
'driver' => 'local',
|
||||||
|
'root' => storage_path('app'),
|
||||||
|
'throw' => false,
|
||||||
|
],
|
||||||
|
'public' => [
|
||||||
|
'driver' => 'local',
|
||||||
|
'root' => storage_path('app/public'),
|
||||||
|
'url' => env('APP_URL').'/storage',
|
||||||
|
'visibility' => 'public',
|
||||||
|
'throw' => false,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
'links' => [
|
||||||
|
public_path('storage') => storage_path('app/public'),
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
15
config/hashing.php
Normal file
15
config/hashing.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'driver' => 'bcrypt',
|
||||||
|
'bcrypt' => [
|
||||||
|
'rounds' => env('BCRYPT_ROUNDS', 10),
|
||||||
|
],
|
||||||
|
'argon' => [
|
||||||
|
'memory' => 1024,
|
||||||
|
'threads' => 2,
|
||||||
|
'time' => 2,
|
||||||
|
],
|
||||||
|
];
|
74
config/logging.php
Normal file
74
config/logging.php
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Monolog\Handler\NullHandler;
|
||||||
|
use Monolog\Handler\StreamHandler;
|
||||||
|
use Monolog\Handler\SyslogUdpHandler;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'default' => env('LOG_CHANNEL', 'stack'),
|
||||||
|
'deprecations' => [
|
||||||
|
'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
|
||||||
|
'trace' => false,
|
||||||
|
],
|
||||||
|
'channels' => [
|
||||||
|
'stack' => [
|
||||||
|
'driver' => 'stack',
|
||||||
|
'channels' => ['single'],
|
||||||
|
'ignore_exceptions' => false,
|
||||||
|
],
|
||||||
|
'single' => [
|
||||||
|
'driver' => 'single',
|
||||||
|
'path' => storage_path('logs/laravel.log'),
|
||||||
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
|
],
|
||||||
|
'daily' => [
|
||||||
|
'driver' => 'daily',
|
||||||
|
'path' => storage_path('logs/laravel.log'),
|
||||||
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
|
'days' => 14,
|
||||||
|
],
|
||||||
|
'slack' => [
|
||||||
|
'driver' => 'slack',
|
||||||
|
'url' => env('LOG_SLACK_WEBHOOK_URL'),
|
||||||
|
'username' => 'Laravel Log',
|
||||||
|
'emoji' => ':boom:',
|
||||||
|
'level' => env('LOG_LEVEL', 'critical'),
|
||||||
|
],
|
||||||
|
'papertrail' => [
|
||||||
|
'driver' => 'monolog',
|
||||||
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
|
'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class),
|
||||||
|
'handler_with' => [
|
||||||
|
'host' => env('PAPERTRAIL_URL'),
|
||||||
|
'port' => env('PAPERTRAIL_PORT'),
|
||||||
|
'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'stderr' => [
|
||||||
|
'driver' => 'monolog',
|
||||||
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
|
'handler' => StreamHandler::class,
|
||||||
|
'formatter' => env('LOG_STDERR_FORMATTER'),
|
||||||
|
'with' => [
|
||||||
|
'stream' => 'php://stderr',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'syslog' => [
|
||||||
|
'driver' => 'syslog',
|
||||||
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
|
],
|
||||||
|
'errorlog' => [
|
||||||
|
'driver' => 'errorlog',
|
||||||
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
|
],
|
||||||
|
'null' => [
|
||||||
|
'driver' => 'monolog',
|
||||||
|
'handler' => NullHandler::class,
|
||||||
|
],
|
||||||
|
'emergency' => [
|
||||||
|
'path' => storage_path('logs/laravel.log'),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
42
config/queue.php
Normal file
42
config/queue.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'default' => env('QUEUE_CONNECTION', 'sync'),
|
||||||
|
'connections' => [
|
||||||
|
'sync' => [
|
||||||
|
'driver' => 'sync',
|
||||||
|
],
|
||||||
|
'database' => [
|
||||||
|
'driver' => 'database',
|
||||||
|
'table' => 'jobs',
|
||||||
|
'queue' => 'default',
|
||||||
|
'retry_after' => 90,
|
||||||
|
'after_commit' => false,
|
||||||
|
],
|
||||||
|
'beanstalkd' => [
|
||||||
|
'driver' => 'beanstalkd',
|
||||||
|
'host' => 'localhost',
|
||||||
|
'queue' => 'default',
|
||||||
|
'retry_after' => 90,
|
||||||
|
'block_for' => 0,
|
||||||
|
'after_commit' => false,
|
||||||
|
],
|
||||||
|
'sqs' => [
|
||||||
|
'driver' => 'sqs',
|
||||||
|
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||||
|
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||||
|
'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
|
||||||
|
'queue' => env('SQS_QUEUE', 'default'),
|
||||||
|
'suffix' => env('SQS_SUFFIX'),
|
||||||
|
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||||
|
'after_commit' => false,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'failed' => [
|
||||||
|
'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'),
|
||||||
|
'database' => env('DB_CONNECTION', 'mysql'),
|
||||||
|
'table' => 'failed_jobs',
|
||||||
|
],
|
||||||
|
];
|
19
config/services.php
Normal file
19
config/services.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'mailgun' => [
|
||||||
|
'domain' => env('MAILGUN_DOMAIN'),
|
||||||
|
'secret' => env('MAILGUN_SECRET'),
|
||||||
|
'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
|
||||||
|
],
|
||||||
|
'postmark' => [
|
||||||
|
'token' => env('POSTMARK_TOKEN'),
|
||||||
|
],
|
||||||
|
'ses' => [
|
||||||
|
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||||
|
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||||
|
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||||
|
],
|
||||||
|
];
|
26
config/session.php
Normal file
26
config/session.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'driver' => env('SESSION_DRIVER', 'file'),
|
||||||
|
'lifetime' => env('SESSION_LIFETIME', 120),
|
||||||
|
'expire_on_close' => false,
|
||||||
|
'encrypt' => false,
|
||||||
|
'files' => storage_path('framework/sessions'),
|
||||||
|
'connection' => env('SESSION_CONNECTION'),
|
||||||
|
'table' => 'sessions',
|
||||||
|
'store' => env('SESSION_STORE'),
|
||||||
|
'lottery' => [2, 100],
|
||||||
|
'cookie' => env(
|
||||||
|
'SESSION_COOKIE',
|
||||||
|
Str::slug(env('APP_NAME', 'KamilCraftAPI'), '_').'_session'
|
||||||
|
),
|
||||||
|
'path' => '/',
|
||||||
|
'domain' => env('SESSION_DOMAIN'),
|
||||||
|
'secure' => env('SESSION_SECURE_COOKIE'),
|
||||||
|
'http_only' => true,
|
||||||
|
'same_site' => 'lax',
|
||||||
|
];
|
13
config/view.php
Normal file
13
config/view.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'paths' => [
|
||||||
|
resource_path('views'),
|
||||||
|
],
|
||||||
|
'compiled' => env(
|
||||||
|
'VIEW_COMPILED_PATH',
|
||||||
|
realpath(storage_path('framework/views'))
|
||||||
|
),
|
||||||
|
];
|
1
database/.gitignore
vendored
Normal file
1
database/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.sqlite*
|
19
database/factories/UserFactory.php
Normal file
19
database/factories/UserFactory.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
class UserFactory extends Factory
|
||||||
|
{
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => $this->faker->name(),
|
||||||
|
'email' => $this->faker->unique()->safeEmail(),
|
||||||
|
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
|
||||||
|
'remember_token' => Str::random(10),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
27
database/migrations/2014_10_12_000000_create_users_table.php
Normal file
27
database/migrations/2014_10_12_000000_create_users_table.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('users', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('email')->unique();
|
||||||
|
$table->string('password');
|
||||||
|
$table->rememberToken();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('users');
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('password_resets', function (Blueprint $table) {
|
||||||
|
$table->string('email')->index();
|
||||||
|
$table->string('token');
|
||||||
|
$table->timestamp('created_at')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('password_resets');
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('failed_jobs', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('uuid')->unique();
|
||||||
|
$table->text('connection');
|
||||||
|
$table->text('queue');
|
||||||
|
$table->longText('payload');
|
||||||
|
$table->longText('exception');
|
||||||
|
$table->timestamp('failed_at')->useCurrent();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('failed_jobs');
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('personal_access_tokens', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->morphs('tokenable');
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('token', 64)->unique();
|
||||||
|
$table->text('abilities')->nullable();
|
||||||
|
$table->timestamp('last_used_at')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('personal_access_tokens');
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('categories', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->char('name', 20)->nullable();
|
||||||
|
$table->char('slug', 20)->unique();
|
||||||
|
$table->integer('priority')->nullable()->default(0);
|
||||||
|
$table->boolean('default')->nullable()->default(false);
|
||||||
|
$table->boolean('visible')->nullable()->default(false);
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('categories');
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('projects', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('title', 255);
|
||||||
|
$table->json('categories')->nullable()->default(null);
|
||||||
|
$table->string('author', 30);
|
||||||
|
$table->json('images')->nullable()->default(null);
|
||||||
|
$table->dateTimeTz('release_date')->nullable()->useCurrent();
|
||||||
|
$table->dateTimeTz('update_date')->nullable()->default(null);
|
||||||
|
$table->string('project_url', 255)->nullable()->default(null);
|
||||||
|
$table->string('project_version', 20)->nullable()->default(null);
|
||||||
|
$table->text('description')->nullable()->default(null);
|
||||||
|
$table->boolean('visible')->nullable()->default(false);
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('projects');
|
||||||
|
}
|
||||||
|
};
|
22
database/seeders/CategorySeeder.php
Normal file
22
database/seeders/CategorySeeder.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\Category;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class CategorySeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$categories = [
|
||||||
|
['name' => 'Wszystkie', 'slug' => 'all', 'default' => true, 'visible' => true],
|
||||||
|
['name' => 'Prywatne', 'slug' => 'private', 'priority' => 1, 'visible' => true],
|
||||||
|
['name' => 'Zlecenie', 'slug' => 'custom', 'priority' => 1, 'visible' => true],
|
||||||
|
['name' => 'Wybrane', 'slug' => 'selected', 'priority' => 1, 'visible' => true],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($categories as $category)
|
||||||
|
Category::query()->create($category);
|
||||||
|
}
|
||||||
|
}
|
14
database/seeders/DatabaseSeeder.php
Normal file
14
database/seeders/DatabaseSeeder.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class DatabaseSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$this->call(CategorySeeder::class);
|
||||||
|
$this->call(UserSeeder::class);
|
||||||
|
}
|
||||||
|
}
|
15
database/seeders/UserSeeder.php
Normal file
15
database/seeders/UserSeeder.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
|
||||||
|
class UserSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
User::factory(['email' => 'admin@example.com'])->create();
|
||||||
|
}
|
||||||
|
}
|
72
docker-compose.yml
Normal file
72
docker-compose.yml
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
nginx:
|
||||||
|
image: nginx:latest
|
||||||
|
container_name: kamilcraft-api_www
|
||||||
|
working_dir: /application
|
||||||
|
ports:
|
||||||
|
- ${EXTERNAL_WEBSERVER_PORT:-80}:80
|
||||||
|
volumes:
|
||||||
|
- ./environment/dev/nginx/default.conf:/etc/nginx/conf.d/default.conf
|
||||||
|
- .:/application
|
||||||
|
networks:
|
||||||
|
- kamilcraft
|
||||||
|
depends_on:
|
||||||
|
- php
|
||||||
|
- db
|
||||||
|
|
||||||
|
php:
|
||||||
|
build:
|
||||||
|
context: environment/dev/php
|
||||||
|
container_name: kamilcraft-api_php
|
||||||
|
working_dir: /application
|
||||||
|
user: ${CURRENT_UID:-1000}
|
||||||
|
volumes:
|
||||||
|
- .:/application
|
||||||
|
- ./environment/dev/php/php.ini:/usr/local/etc/php/conf.d/php.ini
|
||||||
|
networks:
|
||||||
|
- kamilcraft
|
||||||
|
extra_hosts:
|
||||||
|
- host.docker.internal:host-gateway
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
npm:
|
||||||
|
build:
|
||||||
|
context: environment/dev/npm
|
||||||
|
container_name: kamilcraft-api_node
|
||||||
|
working_dir: /application
|
||||||
|
entrypoint: [ 'npm' ]
|
||||||
|
ports:
|
||||||
|
- '3000:3000'
|
||||||
|
- '3001:3001'
|
||||||
|
volumes:
|
||||||
|
- .:/application
|
||||||
|
networks:
|
||||||
|
- kamilcraft
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: mysql:8.0
|
||||||
|
container_name: kamilcraft-api_db
|
||||||
|
ports:
|
||||||
|
- '${DB_PORT}:3306'
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
|
||||||
|
MYSQL_DATABASE: '${DB_DATABASE}'
|
||||||
|
MYSQL_USER: '${DB_USERNAME}'
|
||||||
|
MYSQL_PASSWORD: '${DB_PASSWORD}'
|
||||||
|
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
|
||||||
|
volumes:
|
||||||
|
- 'mysql-db-data:/var/lib/mysql'
|
||||||
|
networks:
|
||||||
|
- kamilcraft
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
networks:
|
||||||
|
kamilcraft:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mysql-db-data:
|
||||||
|
name: ib-mysql-data
|
||||||
|
driver: local
|
21
environment/dev/nginx/default.conf
Normal file
21
environment/dev/nginx/default.conf
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
server {
|
||||||
|
listen 80 default_server;
|
||||||
|
|
||||||
|
index index.php index.html;
|
||||||
|
root /application/public;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.php?$query_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ \.php$ {
|
||||||
|
fastcgi_pass php:9000;
|
||||||
|
fastcgi_index index.php;
|
||||||
|
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
||||||
|
include fastcgi_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ /.ht {
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
}
|
3
environment/dev/npm/Dockerfile
Normal file
3
environment/dev/npm/Dockerfile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
FROM node:18-alpine
|
||||||
|
|
||||||
|
RUN npm install -g npm@latest
|
34
environment/dev/php/Dockerfile
Normal file
34
environment/dev/php/Dockerfile
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
FROM php:8.1-fpm-alpine
|
||||||
|
|
||||||
|
ARG XDEBUG_VERSION=3.1.6
|
||||||
|
ARG INSTALL_XDEBUG=false
|
||||||
|
|
||||||
|
ARG COMPOSER_VERSION=2.4.4
|
||||||
|
ENV COMPOSER_HOME=/application/.composer
|
||||||
|
ENV COMPOSER_MEMORY_LIMIT=-1
|
||||||
|
|
||||||
|
RUN if [ ${INSTALL_XDEBUG} = true ]; then \
|
||||||
|
apk --no-cache add $PHPIZE_DEPS \
|
||||||
|
&& pecl install xdebug-${XDEBUG_VERSION} \
|
||||||
|
&& docker-php-ext-enable xdebug \
|
||||||
|
;fi
|
||||||
|
|
||||||
|
RUN apk update && apk upgrade \
|
||||||
|
&& apk add --no-cache pcre-dev $PHPIZE_DEPS \
|
||||||
|
icu-dev \
|
||||||
|
zip \
|
||||||
|
libzip-dev \
|
||||||
|
libpng-dev \
|
||||||
|
&& curl -sS https://getcomposer.org/installer | php -- --version="${COMPOSER_VERSION}" --install-dir=/usr/local/bin --filename=composer \
|
||||||
|
&& pecl install redis \
|
||||||
|
&& docker-php-ext-install \
|
||||||
|
mysqli \
|
||||||
|
pdo \
|
||||||
|
pdo_mysql \
|
||||||
|
zip \
|
||||||
|
gd \
|
||||||
|
bcmath \
|
||||||
|
&& docker-php-ext-configure \
|
||||||
|
zip \
|
||||||
|
&& docker-php-ext-enable \
|
||||||
|
redis
|
9
environment/dev/php/php.ini
Normal file
9
environment/dev/php/php.ini
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[PHP]
|
||||||
|
memory_limit = 1G
|
||||||
|
|
||||||
|
[xdebug]
|
||||||
|
xdebug.client_host=host.docker.internal
|
||||||
|
xdebug.client_port=9003
|
||||||
|
xdebug.mode=debug
|
||||||
|
xdebug.start_with_request=yes
|
||||||
|
xdebug.log_level=0
|
@ -1,14 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="pl">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport"
|
|
||||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
||||||
<title>Błąd 400</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Błąd 400</h1>
|
|
||||||
<p>Niepoprawne zapytanie!</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,14 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="pl">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport"
|
|
||||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
||||||
<title>Błąd 404</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Błąd 404</h1>
|
|
||||||
<p>Nie znaleziono szukanej strony!</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,14 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="pl">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport"
|
|
||||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
||||||
<title>Błąd 500</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Błąd 500</h1>
|
|
||||||
<p>Wystąpił wewnętrzny błąd serwera!</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
15909
package-lock.json
generated
Normal file
15909
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
21
package.json
Normal file
21
package.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "npm run development",
|
||||||
|
"development": "mix",
|
||||||
|
"watch": "mix watch",
|
||||||
|
"watch-poll": "mix watch -- --watch-options-poll=1000",
|
||||||
|
"hot": "mix watch --hot",
|
||||||
|
"prod": "npm run production",
|
||||||
|
"production": "mix --production"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"axios": "^0.21",
|
||||||
|
"laravel-mix": "^6.0.6",
|
||||||
|
"lodash": "^4.17.19",
|
||||||
|
"postcss": "^8.1.14",
|
||||||
|
"resolve-url-loader": "^5.0.0",
|
||||||
|
"sass": "^1.49.7",
|
||||||
|
"sass-loader": "^12.4.0"
|
||||||
|
}
|
||||||
|
}
|
31
phpunit.xml
Normal file
31
phpunit.xml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
|
||||||
|
bootstrap="vendor/autoload.php"
|
||||||
|
colors="true"
|
||||||
|
>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="Unit">
|
||||||
|
<directory suffix="Test.php">./tests/Unit</directory>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="Feature">
|
||||||
|
<directory suffix="Test.php">./tests/Feature</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
<coverage processUncoveredFiles="true">
|
||||||
|
<include>
|
||||||
|
<directory suffix=".php">./app</directory>
|
||||||
|
</include>
|
||||||
|
</coverage>
|
||||||
|
<php>
|
||||||
|
<server name="APP_ENV" value="testing"/>
|
||||||
|
<server name="BCRYPT_ROUNDS" value="4"/>
|
||||||
|
<server name="CACHE_DRIVER" value="array"/>
|
||||||
|
<!-- <server name="DB_CONNECTION" value="sqlite"/> -->
|
||||||
|
<!-- <server name="DB_DATABASE" value=":memory:"/> -->
|
||||||
|
<server name="MAIL_MAILER" value="array"/>
|
||||||
|
<server name="QUEUE_CONNECTION" value="sync"/>
|
||||||
|
<server name="SESSION_DRIVER" value="array"/>
|
||||||
|
<server name="TELESCOPE_ENABLED" value="false"/>
|
||||||
|
</php>
|
||||||
|
</phpunit>
|
21
public/.htaccess
Normal file
21
public/.htaccess
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<IfModule mod_rewrite.c>
|
||||||
|
<IfModule mod_negotiation.c>
|
||||||
|
Options -MultiViews -Indexes
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
RewriteEngine On
|
||||||
|
|
||||||
|
# Handle Authorization Header
|
||||||
|
RewriteCond %{HTTP:Authorization} .
|
||||||
|
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||||
|
|
||||||
|
# Redirect Trailing Slashes If Not A Folder...
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
RewriteCond %{REQUEST_URI} (.+)/$
|
||||||
|
RewriteRule ^ %1 [L,R=301]
|
||||||
|
|
||||||
|
# Send Requests To Front Controller...
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteRule ^ index.php [L]
|
||||||
|
</IfModule>
|
2
public/css/.gitignore
vendored
Normal file
2
public/css/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
0
public/favicon.ico
Normal file
0
public/favicon.ico
Normal file
@ -1,10 +1,55 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
const ROOT_PATH = __DIR__ . '/../';
|
use Illuminate\Contracts\Http\Kernel;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
use KamilCraftApi\Application;
|
define('LARAVEL_START', microtime(true));
|
||||||
|
|
||||||
require ROOT_PATH . 'vendor/autoload.php';
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Check If The Application Is Under Maintenance
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| If the application is in maintenance / demo mode via the "down" command
|
||||||
|
| we will load this file so that any pre-rendered content can be shown
|
||||||
|
| instead of starting the framework, which could cause an exception.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
$app = new Application(ROOT_PATH . '.env');
|
if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
|
||||||
$app->run();
|
require $maintenance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Register The Auto Loader
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Composer provides a convenient, automatically generated class loader for
|
||||||
|
| this application. We just need to utilize it! We'll simply require it
|
||||||
|
| into the script here so we don't need to manually load our classes.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
require __DIR__.'/../vendor/autoload.php';
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Run The Application
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Once we have the application, we can handle the incoming request using
|
||||||
|
| the application's HTTP kernel. Then, we will send the response back
|
||||||
|
| to this client's browser, allowing them to enjoy our application.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
$app = require_once __DIR__.'/../bootstrap/app.php';
|
||||||
|
|
||||||
|
$kernel = $app->make(Kernel::class);
|
||||||
|
|
||||||
|
$response = $kernel->handle(
|
||||||
|
$request = Request::capture()
|
||||||
|
)->send();
|
||||||
|
|
||||||
|
$kernel->terminate($request, $response);
|
||||||
|
2
public/js/.gitignore
vendored
Normal file
2
public/js/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
5
public/mix-manifest.json
Normal file
5
public/mix-manifest.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"/js/app.js": "/js/app.js",
|
||||||
|
"/css/dashboard.css": "/css/dashboard.css",
|
||||||
|
"/css/app.css": "/css/app.css"
|
||||||
|
}
|
2
public/robots.txt
Normal file
2
public/robots.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
User-agent: *
|
||||||
|
Disallow:
|
1
resources/js/app.js
vendored
Normal file
1
resources/js/app.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
require('./bootstrap');
|
28
resources/js/bootstrap.js
vendored
Normal file
28
resources/js/bootstrap.js
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
window._ = require('lodash');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We'll load the axios HTTP library which allows us to easily issue requests
|
||||||
|
* to our Laravel back-end. This library automatically handles sending the
|
||||||
|
* CSRF token as a header based on the value of the "XSRF" token cookie.
|
||||||
|
*/
|
||||||
|
|
||||||
|
window.axios = require('axios');
|
||||||
|
|
||||||
|
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Echo exposes an expressive API for subscribing to channels and listening
|
||||||
|
* for events that are broadcast by Laravel. Echo and event broadcasting
|
||||||
|
* allows your team to easily build robust real-time web applications.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// import Echo from 'laravel-echo';
|
||||||
|
|
||||||
|
// window.Pusher = require('pusher-js');
|
||||||
|
|
||||||
|
// window.Echo = new Echo({
|
||||||
|
// broadcaster: 'pusher',
|
||||||
|
// key: process.env.MIX_PUSHER_APP_KEY,
|
||||||
|
// cluster: process.env.MIX_PUSHER_APP_CLUSTER,
|
||||||
|
// forceTLS: true
|
||||||
|
// });
|
@ -1,24 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"name": "Wszystkie",
|
|
||||||
"slug": "all",
|
|
||||||
"default": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"name": "Prywatne",
|
|
||||||
"slug": "private"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 4,
|
|
||||||
"name": "Zlecenie",
|
|
||||||
"slug": "custom"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 5,
|
|
||||||
"name": "Wybrane",
|
|
||||||
"slug": "selected",
|
|
||||||
"visible": false
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,24 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"title": "Memstacja.pl",
|
|
||||||
"categories": ["selected", "private"],
|
|
||||||
"author": "Kamil Niemczycki",
|
|
||||||
"image": "assets/img/projects/kamilcraft.jpg",
|
|
||||||
"release_data": "28 sierpnia 2021",
|
|
||||||
"project_url": "https://memstacja.pl",
|
|
||||||
"version": "v1.4.9",
|
|
||||||
"description": "Memstacja.pl jest to strona z memami. Umożliwia dodanie własnego mema przez panel administracyjny, nadanie tagów i opisu. Użytkownicy mogą głosować przy użyciu serduszek, mając wpływ na pozycję danego mema na liście polecanych i TOP 10."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"title": "edwardgoff-art.co.uk",
|
|
||||||
"categories": ["selected", "custom"],
|
|
||||||
"author": "Kamil Niemczycki",
|
|
||||||
"image": "assets/img/projects/edward.jpg",
|
|
||||||
"release_data": "25 sierpnia 2021",
|
|
||||||
"project_url": "https://edwardgoff-art.co.uk",
|
|
||||||
"version": "v1.1.4",
|
|
||||||
"description": "Strona jest wizytówką autora i galerią jego prac. Strona umożliwa tworzenie, a także dodawanie zdjęć i opisów dla utworzonych galerii."
|
|
||||||
}
|
|
||||||
]
|
|
20
resources/lang/en/auth.php
Normal file
20
resources/lang/en/auth.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Authentication Language Lines
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The following language lines are used during authentication for various
|
||||||
|
| messages that we need to display to the user. You are free to modify
|
||||||
|
| these language lines according to your application's requirements.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'failed' => 'These credentials do not match our records.',
|
||||||
|
'password' => 'The provided password is incorrect.',
|
||||||
|
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
|
||||||
|
|
||||||
|
];
|
19
resources/lang/en/pagination.php
Normal file
19
resources/lang/en/pagination.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Pagination Language Lines
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The following language lines are used by the paginator library to build
|
||||||
|
| the simple pagination links. You are free to change them to anything
|
||||||
|
| you want to customize your views to better match your application.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'previous' => '« Previous',
|
||||||
|
'next' => 'Next »',
|
||||||
|
|
||||||
|
];
|
22
resources/lang/en/passwords.php
Normal file
22
resources/lang/en/passwords.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Password Reset Language Lines
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The following language lines are the default lines which match reasons
|
||||||
|
| that are given by the password broker for a password update attempt
|
||||||
|
| has failed, such as for an invalid token or invalid new password.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'reset' => 'Your password has been reset!',
|
||||||
|
'sent' => 'We have emailed your password reset link!',
|
||||||
|
'throttled' => 'Please wait before retrying.',
|
||||||
|
'token' => 'This password reset token is invalid.',
|
||||||
|
'user' => "We can't find a user with that email address.",
|
||||||
|
|
||||||
|
];
|
162
resources/lang/en/validation.php
Normal file
162
resources/lang/en/validation.php
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Validation Language Lines
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The following language lines contain the default error messages used by
|
||||||
|
| the validator class. Some of these rules have multiple versions such
|
||||||
|
| as the size rules. Feel free to tweak each of these messages here.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'accepted' => 'The :attribute must be accepted.',
|
||||||
|
'accepted_if' => 'The :attribute must be accepted when :other is :value.',
|
||||||
|
'active_url' => 'The :attribute is not a valid URL.',
|
||||||
|
'after' => 'The :attribute must be a date after :date.',
|
||||||
|
'after_or_equal' => 'The :attribute must be a date after or equal to :date.',
|
||||||
|
'alpha' => 'The :attribute must only contain letters.',
|
||||||
|
'alpha_dash' => 'The :attribute must only contain letters, numbers, dashes and underscores.',
|
||||||
|
'alpha_num' => 'The :attribute must only contain letters and numbers.',
|
||||||
|
'array' => 'The :attribute must be an array.',
|
||||||
|
'before' => 'The :attribute must be a date before :date.',
|
||||||
|
'before_or_equal' => 'The :attribute must be a date before or equal to :date.',
|
||||||
|
'between' => [
|
||||||
|
'numeric' => 'The :attribute must be between :min and :max.',
|
||||||
|
'file' => 'The :attribute must be between :min and :max kilobytes.',
|
||||||
|
'string' => 'The :attribute must be between :min and :max characters.',
|
||||||
|
'array' => 'The :attribute must have between :min and :max items.',
|
||||||
|
],
|
||||||
|
'boolean' => 'The :attribute field must be true or false.',
|
||||||
|
'confirmed' => 'The :attribute confirmation does not match.',
|
||||||
|
'current_password' => 'The password is incorrect.',
|
||||||
|
'date' => 'The :attribute is not a valid date.',
|
||||||
|
'date_equals' => 'The :attribute must be a date equal to :date.',
|
||||||
|
'date_format' => 'The :attribute does not match the format :format.',
|
||||||
|
'declined' => 'The :attribute must be declined.',
|
||||||
|
'declined_if' => 'The :attribute must be declined when :other is :value.',
|
||||||
|
'different' => 'The :attribute and :other must be different.',
|
||||||
|
'digits' => 'The :attribute must be :digits digits.',
|
||||||
|
'digits_between' => 'The :attribute must be between :min and :max digits.',
|
||||||
|
'dimensions' => 'The :attribute has invalid image dimensions.',
|
||||||
|
'distinct' => 'The :attribute field has a duplicate value.',
|
||||||
|
'email' => 'The :attribute must be a valid email address.',
|
||||||
|
'ends_with' => 'The :attribute must end with one of the following: :values.',
|
||||||
|
'enum' => 'The selected :attribute is invalid.',
|
||||||
|
'exists' => 'The selected :attribute is invalid.',
|
||||||
|
'file' => 'The :attribute must be a file.',
|
||||||
|
'filled' => 'The :attribute field must have a value.',
|
||||||
|
'gt' => [
|
||||||
|
'numeric' => 'The :attribute must be greater than :value.',
|
||||||
|
'file' => 'The :attribute must be greater than :value kilobytes.',
|
||||||
|
'string' => 'The :attribute must be greater than :value characters.',
|
||||||
|
'array' => 'The :attribute must have more than :value items.',
|
||||||
|
],
|
||||||
|
'gte' => [
|
||||||
|
'numeric' => 'The :attribute must be greater than or equal to :value.',
|
||||||
|
'file' => 'The :attribute must be greater than or equal to :value kilobytes.',
|
||||||
|
'string' => 'The :attribute must be greater than or equal to :value characters.',
|
||||||
|
'array' => 'The :attribute must have :value items or more.',
|
||||||
|
],
|
||||||
|
'image' => 'The :attribute must be an image.',
|
||||||
|
'in' => 'The selected :attribute is invalid.',
|
||||||
|
'in_array' => 'The :attribute field does not exist in :other.',
|
||||||
|
'integer' => 'The :attribute must be an integer.',
|
||||||
|
'ip' => 'The :attribute must be a valid IP address.',
|
||||||
|
'ipv4' => 'The :attribute must be a valid IPv4 address.',
|
||||||
|
'ipv6' => 'The :attribute must be a valid IPv6 address.',
|
||||||
|
'mac_address' => 'The :attribute must be a valid MAC address.',
|
||||||
|
'json' => 'The :attribute must be a valid JSON string.',
|
||||||
|
'lt' => [
|
||||||
|
'numeric' => 'The :attribute must be less than :value.',
|
||||||
|
'file' => 'The :attribute must be less than :value kilobytes.',
|
||||||
|
'string' => 'The :attribute must be less than :value characters.',
|
||||||
|
'array' => 'The :attribute must have less than :value items.',
|
||||||
|
],
|
||||||
|
'lte' => [
|
||||||
|
'numeric' => 'The :attribute must be less than or equal to :value.',
|
||||||
|
'file' => 'The :attribute must be less than or equal to :value kilobytes.',
|
||||||
|
'string' => 'The :attribute must be less than or equal to :value characters.',
|
||||||
|
'array' => 'The :attribute must not have more than :value items.',
|
||||||
|
],
|
||||||
|
'max' => [
|
||||||
|
'numeric' => 'The :attribute must not be greater than :max.',
|
||||||
|
'file' => 'The :attribute must not be greater than :max kilobytes.',
|
||||||
|
'string' => 'The :attribute must not be greater than :max characters.',
|
||||||
|
'array' => 'The :attribute must not have more than :max items.',
|
||||||
|
],
|
||||||
|
'mimes' => 'The :attribute must be a file of type: :values.',
|
||||||
|
'mimetypes' => 'The :attribute must be a file of type: :values.',
|
||||||
|
'min' => [
|
||||||
|
'numeric' => 'The :attribute must be at least :min.',
|
||||||
|
'file' => 'The :attribute must be at least :min kilobytes.',
|
||||||
|
'string' => 'The :attribute must be at least :min characters.',
|
||||||
|
'array' => 'The :attribute must have at least :min items.',
|
||||||
|
],
|
||||||
|
'multiple_of' => 'The :attribute must be a multiple of :value.',
|
||||||
|
'not_in' => 'The selected :attribute is invalid.',
|
||||||
|
'not_regex' => 'The :attribute format is invalid.',
|
||||||
|
'numeric' => 'The :attribute must be a number.',
|
||||||
|
'password' => 'The password is incorrect.',
|
||||||
|
'present' => 'The :attribute field must be present.',
|
||||||
|
'prohibited' => 'The :attribute field is prohibited.',
|
||||||
|
'prohibited_if' => 'The :attribute field is prohibited when :other is :value.',
|
||||||
|
'prohibited_unless' => 'The :attribute field is prohibited unless :other is in :values.',
|
||||||
|
'prohibits' => 'The :attribute field prohibits :other from being present.',
|
||||||
|
'regex' => 'The :attribute format is invalid.',
|
||||||
|
'required' => 'The :attribute field is required.',
|
||||||
|
'required_if' => 'The :attribute field is required when :other is :value.',
|
||||||
|
'required_unless' => 'The :attribute field is required unless :other is in :values.',
|
||||||
|
'required_with' => 'The :attribute field is required when :values is present.',
|
||||||
|
'required_with_all' => 'The :attribute field is required when :values are present.',
|
||||||
|
'required_without' => 'The :attribute field is required when :values is not present.',
|
||||||
|
'required_without_all' => 'The :attribute field is required when none of :values are present.',
|
||||||
|
'same' => 'The :attribute and :other must match.',
|
||||||
|
'size' => [
|
||||||
|
'numeric' => 'The :attribute must be :size.',
|
||||||
|
'file' => 'The :attribute must be :size kilobytes.',
|
||||||
|
'string' => 'The :attribute must be :size characters.',
|
||||||
|
'array' => 'The :attribute must contain :size items.',
|
||||||
|
],
|
||||||
|
'starts_with' => 'The :attribute must start with one of the following: :values.',
|
||||||
|
'string' => 'The :attribute must be a string.',
|
||||||
|
'timezone' => 'The :attribute must be a valid timezone.',
|
||||||
|
'unique' => 'The :attribute has already been taken.',
|
||||||
|
'uploaded' => 'The :attribute failed to upload.',
|
||||||
|
'url' => 'The :attribute must be a valid URL.',
|
||||||
|
'uuid' => 'The :attribute must be a valid UUID.',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Custom Validation Language Lines
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may specify custom validation messages for attributes using the
|
||||||
|
| convention "attribute.rule" to name the lines. This makes it quick to
|
||||||
|
| specify a specific custom language line for a given attribute rule.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'custom' => [
|
||||||
|
'attribute-name' => [
|
||||||
|
'rule-name' => 'custom-message',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Custom Validation Attributes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The following language lines are used to swap our attribute placeholder
|
||||||
|
| with something more reader friendly such as "E-Mail Address" instead
|
||||||
|
| of "email". This simply helps us make our message more expressive.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'attributes' => [],
|
||||||
|
|
||||||
|
];
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user