Initial Commit
This commit is contained in:
commit
225b326a5e
38
app/Exports/RolesExport.php
Normal file
38
app/Exports/RolesExport.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Exports;
|
||||||
|
|
||||||
|
use Maatwebsite\Excel\Concerns\FromCollection;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||||
|
use Modules\Usermanagement\Models\Role;
|
||||||
|
|
||||||
|
class RolesExport implements WithColumnFormatting, WithHeadings, FromCollection, withMapping
|
||||||
|
{
|
||||||
|
public function collection(){
|
||||||
|
return Role::all();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function map($row): array{
|
||||||
|
return [
|
||||||
|
$row->id,
|
||||||
|
$row->name,
|
||||||
|
$row->created_at
|
||||||
|
];
|
||||||
|
}
|
||||||
|
public function headings(): array{
|
||||||
|
return [
|
||||||
|
'ID',
|
||||||
|
'Role',
|
||||||
|
'Created At'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function columnFormats(): array{
|
||||||
|
return [
|
||||||
|
'A' => \PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_NUMBER,
|
||||||
|
'C' => \PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_DATETIME
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
41
app/Exports/UsersExport.php
Normal file
41
app/Exports/UsersExport.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Exports;
|
||||||
|
|
||||||
|
use Maatwebsite\Excel\Concerns\FromCollection;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
|
||||||
|
use Modules\Usermanagement\Models\User;
|
||||||
|
|
||||||
|
class UsersExport implements WithColumnFormatting, WithHeadings, FromCollection, withMapping
|
||||||
|
{
|
||||||
|
public function collection(){
|
||||||
|
return User::all();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function map($row): array{
|
||||||
|
return [
|
||||||
|
$row->id,
|
||||||
|
$row->name,
|
||||||
|
$row->email,
|
||||||
|
$row->created_at
|
||||||
|
];
|
||||||
|
}
|
||||||
|
public function headings(): array{
|
||||||
|
return [
|
||||||
|
'ID',
|
||||||
|
'Name',
|
||||||
|
'Email',
|
||||||
|
'Created At'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function columnFormats(): array{
|
||||||
|
return [
|
||||||
|
'A' => \PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_NUMBER,
|
||||||
|
'C' => \PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_DATETIME
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
0
app/Http/Controllers/.gitkeep
Normal file
0
app/Http/Controllers/.gitkeep
Normal file
69
app/Http/Controllers/PermissionsController.php
Normal file
69
app/Http/Controllers/PermissionsController.php
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class PermissionsController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\View
|
||||||
|
* @return \Illuminate\Contracts\View\Factory
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('usermanagement::index');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*
|
||||||
|
* This function is responsible for displaying the form to create a new resource.
|
||||||
|
* It returns the view for creating a new resource, which is located at 'usermanagement::create'.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||||
|
* @return \Illuminate\Contracts\View\View
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
return view('usermanagement::create');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
: RedirectResponse
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function show($id)
|
||||||
|
{
|
||||||
|
return view('usermanagement::show');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
return view('usermanagement::edit');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function update(Request $request, $id)
|
||||||
|
: RedirectResponse
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
291
app/Http/Controllers/RolesController.php
Normal file
291
app/Http/Controllers/RolesController.php
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
|
use Modules\Usermanagement\Exports\RolesExport;
|
||||||
|
use Modules\Usermanagement\Http\Requests\RoleRequest;
|
||||||
|
use Modules\Usermanagement\Models\Role;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RolesController
|
||||||
|
*
|
||||||
|
* This controller is responsible for managing user roles within the application.
|
||||||
|
*
|
||||||
|
* @package Modules\Usermanagement\Http\Controllers
|
||||||
|
*/
|
||||||
|
class RolesController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \Illuminate\Contracts\Auth\Authenticatable|null
|
||||||
|
*/
|
||||||
|
public $user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UsersController constructor.
|
||||||
|
*
|
||||||
|
* Initializes the user property with the authenticated user.
|
||||||
|
*
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->middleware(function ($request, $next) {
|
||||||
|
$this->user = Auth::guard('web')->user();
|
||||||
|
return $next($request);
|
||||||
|
});
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
// Check if the authenticated user has the required permission to view roles
|
||||||
|
if (is_null($this->user) || !$this->user->can('roles.view')) {
|
||||||
|
//abort(403, 'Sorry! You are not allowed to view roles.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch all roles from the database
|
||||||
|
$roles = Role::all();
|
||||||
|
|
||||||
|
// Return the view for displaying the roles
|
||||||
|
return view('usermanagement::roles.index', compact('roles'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function store(RoleRequest $request)
|
||||||
|
{
|
||||||
|
// Check if the authenticated user has the required permission to store roles
|
||||||
|
if (is_null($this->user) || !$this->user->can('roles.store')) {
|
||||||
|
//abort(403, 'Sorry! You are not allowed to store roles.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new role using the provided request data
|
||||||
|
Role::create($request->all());
|
||||||
|
|
||||||
|
// Redirect back to the roles index with a success message
|
||||||
|
return redirect()->route('users.roles.index')->with('success', 'Role created successfully.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
// Check if the authenticated user has the required permission to create roles
|
||||||
|
if (is_null($this->user) || !$this->user->can('roles.create')) {
|
||||||
|
//abort(403, 'Sorry! You are not allowed to create roles.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the view for creating a new role
|
||||||
|
return view('usermanagement::roles.create');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function show($id)
|
||||||
|
{
|
||||||
|
// Check if the authenticated user has the required permission to view roles
|
||||||
|
if (is_null($this->user) || !$this->user->can('roles.view')) {
|
||||||
|
abort(403, 'Sorry! You are not allowed to view roles.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the specified role from the database
|
||||||
|
$role = Role::find($id);
|
||||||
|
|
||||||
|
// Return the view for displaying the role
|
||||||
|
return view('usermanagement::roles.show', compact('role'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
// Check if the authenticated user has the required permission to edit roles
|
||||||
|
if (is_null($this->user) || !$this->user->can('roles.edit')) {
|
||||||
|
//abort(403, 'Sorry! You are not allowed to edit roles.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the specified role from the database
|
||||||
|
$role = Role::find($id);
|
||||||
|
|
||||||
|
// Return the view for editing the role
|
||||||
|
return view('usermanagement::roles.create', compact('role'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified role in storage.
|
||||||
|
*
|
||||||
|
* @param \Modules\Usermanagement\Http\Requests\RoleRequest $request The request object containing the role data.
|
||||||
|
* @param int $id The unique identifier of the role to be updated.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse Redirects back to the roles index with a success message upon successful update.
|
||||||
|
*
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException If the authenticated user does not have the required permission to update roles.
|
||||||
|
*/
|
||||||
|
public function update(RoleRequest $request, $id)
|
||||||
|
{
|
||||||
|
// Check if the authenticated user has the required permission to update roles
|
||||||
|
if (is_null($this->user) || !$this->user->can('roles.update')) {
|
||||||
|
//abort(403, 'Sorry! You are not allowed to update roles.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the specified role from the database
|
||||||
|
$role = Role::find($id);
|
||||||
|
|
||||||
|
// Update the role using the provided request data
|
||||||
|
$role->update($request->all());
|
||||||
|
|
||||||
|
// Redirect back to the roles index with a success message
|
||||||
|
return redirect()->route('users.roles.index')->with('success', 'Role updated successfully.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
// Check if the authenticated user has the required permission to delete roles
|
||||||
|
if (is_null($this->user) || !$this->user->can('roles.delete')) {
|
||||||
|
//abort(403, 'Sorry! You are not allowed to delete roles.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the specified role from the database
|
||||||
|
$role = Role::find($id);
|
||||||
|
|
||||||
|
// Delete the role
|
||||||
|
$role->delete();
|
||||||
|
|
||||||
|
// Redirect back to the roles index with a success message
|
||||||
|
echo json_encode(['message' => 'User deleted successfully.', 'success' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore a deleted role.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function restore($id)
|
||||||
|
{
|
||||||
|
// Check if the authenticated user has the required permission to restore roles
|
||||||
|
if (is_null($this->user) || !$this->user->can('roles.restore')) {
|
||||||
|
abort(403, 'Sorry! You are not allowed to restore roles.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the specified role from the database
|
||||||
|
$role = Role::withTrashed()->find($id);
|
||||||
|
|
||||||
|
// Restore the role
|
||||||
|
$role->restore();
|
||||||
|
|
||||||
|
// Redirect back to the roles index with a success message
|
||||||
|
return redirect()->route('users.roles.index')->with('success', 'Role restored successfully.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process support datatables ajax request.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function dataForDatatables(Request $request)
|
||||||
|
{
|
||||||
|
if (is_null($this->user) || !$this->user->can('roles.view')) {
|
||||||
|
//abort(403, 'Sorry! You are not allowed to view users.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve data from the database
|
||||||
|
$query = Role::query();
|
||||||
|
|
||||||
|
// Apply search filter if provided
|
||||||
|
if ($request->has('search') && !empty($request->get('search'))) {
|
||||||
|
$search = $request->get('search');
|
||||||
|
$query->where(function ($q) use ($search) {
|
||||||
|
$q->where('name', 'LIKE', "%$search%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply sorting if provided
|
||||||
|
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||||
|
$order = $request->get('sortOrder');
|
||||||
|
$column = $request->get('sortField');
|
||||||
|
$query->orderBy($column, $order);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the total count of records
|
||||||
|
$totalRecords = $query->count();
|
||||||
|
|
||||||
|
// Apply pagination if provided
|
||||||
|
if ($request->has('start') && $request->has('length')) {
|
||||||
|
$start = $request->get('start');
|
||||||
|
$length = $request->get('length');
|
||||||
|
$query->skip($start)->take($length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the filtered count of records
|
||||||
|
$filteredRecords = $query->count();
|
||||||
|
|
||||||
|
// Get the data for the current page
|
||||||
|
$roles = $query->get();
|
||||||
|
|
||||||
|
// Calculate the page count
|
||||||
|
$pageCount = ceil($totalRecords);
|
||||||
|
|
||||||
|
// Calculate the current page number
|
||||||
|
$currentPage = 0 + 1;
|
||||||
|
|
||||||
|
// Return the response data as a JSON object
|
||||||
|
return response()->json([
|
||||||
|
'draw' => $request->get('draw'),
|
||||||
|
'recordsTotal' => $totalRecords,
|
||||||
|
'recordsFiltered' => $filteredRecords,
|
||||||
|
'pageCount' => $pageCount,
|
||||||
|
'page' => $currentPage,
|
||||||
|
'totalCount' => $totalRecords,
|
||||||
|
'data' => $roles,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function export()
|
||||||
|
{
|
||||||
|
return Excel::download(new RolesExport, 'roles.xlsx');
|
||||||
|
}
|
||||||
|
}
|
249
app/Http/Controllers/UsersController.php
Normal file
249
app/Http/Controllers/UsersController.php
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
|
use Modules\Usermanagement\Exports\UsersExport;
|
||||||
|
use Modules\Usermanagement\Http\Requests\User as UserRequest;
|
||||||
|
use Modules\Usermanagement\Models\Role;
|
||||||
|
use Modules\Usermanagement\Models\User;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class UsersController
|
||||||
|
*
|
||||||
|
* This controller is responsible for managing user within the application.
|
||||||
|
*
|
||||||
|
* @package Modules\Usermanagement\Http\Controllers
|
||||||
|
*/
|
||||||
|
class UsersController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \Illuminate\Contracts\Auth\Authenticatable|null
|
||||||
|
*/
|
||||||
|
public $user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UsersController constructor.
|
||||||
|
*
|
||||||
|
* Initializes the user property with the authenticated user.
|
||||||
|
*/
|
||||||
|
// public function __construct()
|
||||||
|
// {
|
||||||
|
// $this->middleware(function ($request, $next) {
|
||||||
|
// $this->user = Auth::guard('web')->user();
|
||||||
|
// return $next($request);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
if (is_null($this->user) || !$this->user->can('users.view')) {
|
||||||
|
//abort(403, 'Sorry! You are not allowed to view users.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('usermanagement::users.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process support datatables ajax request.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function dataForDatatables(Request $request)
|
||||||
|
{
|
||||||
|
if (is_null($this->user) || !$this->user->can('users.view')) {
|
||||||
|
//abort(403, 'Sorry! You are not allowed to view users.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve data from the database
|
||||||
|
$query = User::query();
|
||||||
|
|
||||||
|
// Apply search filter if provided
|
||||||
|
if ($request->has('search') && !empty($request->get('search'))) {
|
||||||
|
$search = $request->get('search');
|
||||||
|
$query->where(function ($q) use ($search) {
|
||||||
|
$q->where('name', 'LIKE', "%$search%")
|
||||||
|
->orWhere('email', 'LIKE', "%$search%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply sorting if provided
|
||||||
|
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||||
|
$order = $request->get('sortOrder');
|
||||||
|
$column = $request->get('sortField');
|
||||||
|
$query->orderBy($column, $order);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the total count of records
|
||||||
|
$totalRecords = $query->count();
|
||||||
|
|
||||||
|
// Apply pagination if provided
|
||||||
|
if ($request->has('start') && $request->has('length')) {
|
||||||
|
$start = $request->get('start');
|
||||||
|
$length = $request->get('length');
|
||||||
|
$query->skip($start)->take($length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the filtered count of records
|
||||||
|
$filteredRecords = $query->count();
|
||||||
|
|
||||||
|
// Get the data for the current page
|
||||||
|
$users = $query->get();
|
||||||
|
|
||||||
|
// Calculate the page count
|
||||||
|
$pageCount = ceil($totalRecords);
|
||||||
|
|
||||||
|
// Calculate the current page number
|
||||||
|
$currentPage = 0 + 1;
|
||||||
|
|
||||||
|
// Return the response data as a JSON object
|
||||||
|
return response()->json([
|
||||||
|
'draw' => $request->get('draw'),
|
||||||
|
'recordsTotal' => $totalRecords,
|
||||||
|
'recordsFiltered' => $filteredRecords,
|
||||||
|
'pageCount' => $pageCount,
|
||||||
|
'page' => $currentPage,
|
||||||
|
'totalCount' => $totalRecords,
|
||||||
|
'data' => $users,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
if (is_null($this->user) || !$this->user->can('users.edit')) {
|
||||||
|
//abort(403, 'Sorry! You are not allowed to edit users.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::find($id);
|
||||||
|
$roles = Role::all();
|
||||||
|
return view('usermanagement::users.create', compact('user', 'roles'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Modules\Usermanagement\Http\Requests\User $request
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function update(UserRequest $request, $id)
|
||||||
|
{
|
||||||
|
if (is_null($this->user) || !$this->user->can('users.update')) {
|
||||||
|
//abort(403, 'Sorry! You are not allowed to update users.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::find($id);
|
||||||
|
$user->update($request->all());
|
||||||
|
|
||||||
|
return redirect()->route('users.index')->with('success', 'User updated successfully.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
if (is_null($this->user) || !$this->user->can('users.delete')) {
|
||||||
|
//abort(403, 'Sorry! You are not allowed to delete users.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::find($id);
|
||||||
|
$user->delete();
|
||||||
|
|
||||||
|
echo json_encode(['message' => 'User deleted successfully.', 'success' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function restore($id)
|
||||||
|
{
|
||||||
|
if (is_null($this->user) || !$this->user->can('users.restore')) {
|
||||||
|
abort(403, 'Sorry! You are not allowed to restore users.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::withTrashed()->find($id);
|
||||||
|
$user->restore();
|
||||||
|
|
||||||
|
return redirect()->route('users.index')->with('success', 'User restored successfully.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* This function handles the creation of a new user in the application. It validates the incoming request data,
|
||||||
|
* creates a new user record in the database, and redirects the user to the users index page with a success message.
|
||||||
|
*
|
||||||
|
* @param \Modules\Usermanagement\Http\Requests\User $request The incoming request containing the user data.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse Redirects to the users index page with a success message upon successful creation.
|
||||||
|
* @return \Illuminate\Http\RedirectResponse Redirects to the users create page upon validation failure.
|
||||||
|
*/
|
||||||
|
public function store(UserRequest $request)
|
||||||
|
{
|
||||||
|
$validated = $request->validated();
|
||||||
|
|
||||||
|
if ($validated) {
|
||||||
|
$user = User::create($validated);
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
return redirect()->route('users.index')->with('success', 'User created successfully.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('users.create');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
if (is_null($this->user) || !$this->user->can('users.create')) {
|
||||||
|
//abort(403, 'Sorry! You are not allowed to create a user.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$roles = Role::all();
|
||||||
|
return view('usermanagement::users.create', compact('roles'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function export()
|
||||||
|
{
|
||||||
|
return Excel::download(new UsersExport, 'users.xlsx');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
23
app/Http/Requests/ChangePassword.php
Normal file
23
app/Http/Requests/ChangePassword.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class ChangePassword extends FormRequest
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of validation rules for the password and current password fields.
|
||||||
|
*
|
||||||
|
* @return array The validation rules for the password and current password fields.
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
: array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'password' => 'required|string|min:8|confirmed',
|
||||||
|
'current_password' => 'required|string|min:8'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
22
app/Http/Requests/Login.php
Normal file
22
app/Http/Requests/Login.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class Login extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns an array of validation rules for the login form.
|
||||||
|
*
|
||||||
|
* @return array The validation rules.
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
: array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'email' => 'required|email',
|
||||||
|
'password' => 'required'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
46
app/Http/Requests/RoleRequest.php
Normal file
46
app/Http/Requests/RoleRequest.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
|
||||||
|
class RoleRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of validation rules for the registration form.
|
||||||
|
*
|
||||||
|
* @return array The validation rules.
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
: array
|
||||||
|
{
|
||||||
|
|
||||||
|
$rules = [
|
||||||
|
'guard_names' => 'required|string|in:web,api',
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($this->method() === 'PUT') {
|
||||||
|
$rules['name'] = 'required|string|max:255|unique:roles,name,' . $this->id;
|
||||||
|
} else {
|
||||||
|
$rules['name'] = 'required|string|max:255';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepareForValidation()
|
||||||
|
{
|
||||||
|
$this->merge([
|
||||||
|
'guard_names' => 'web',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
49
app/Http/Requests/User.php
Normal file
49
app/Http/Requests/User.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
|
||||||
|
class User extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of validation rules for the registration form.
|
||||||
|
*
|
||||||
|
* @return array The validation rules.
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
: array
|
||||||
|
{
|
||||||
|
|
||||||
|
$rules = [
|
||||||
|
'name' => 'required|string|max:255',
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($this->password || $this->method() === 'POST') {
|
||||||
|
$rules['email'] = 'required|email|unique:users,email';
|
||||||
|
$rules['password'] = 'required|string|min:8|confirmed';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->method() === 'PUT') {
|
||||||
|
$rules['email'] = 'required|email|unique:users,email,' . $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function passedValidation()
|
||||||
|
{
|
||||||
|
$this->merge([
|
||||||
|
'password' => Hash::make($this->password)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
51
app/Models/Base.php
Normal file
51
app/Models/Base.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
use Spatie\Activitylog\LogOptions;
|
||||||
|
use Spatie\Activitylog\Traits\LogsActivity;
|
||||||
|
use Wildside\Userstamps\Userstamps;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Base extends Model
|
||||||
|
{
|
||||||
|
use LogsActivity, SoftDeletes, Userstamps;
|
||||||
|
|
||||||
|
protected $connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new instance of the class.
|
||||||
|
*
|
||||||
|
* @param array $attributes Optional attributes to initialize the object with.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(array $attributes = [])
|
||||||
|
{
|
||||||
|
parent::__construct($attributes);
|
||||||
|
|
||||||
|
// Retrieve the module configuration from the module.json file
|
||||||
|
$modulePath = dirname(__FILE__, 3) . '/module.json';
|
||||||
|
$module = file_get_contents($modulePath);
|
||||||
|
$module = json_decode($module);
|
||||||
|
|
||||||
|
// Set the connection property to the database connection specified in the module configuration
|
||||||
|
$this->connection = $module->database;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the activity log options for the User Management.
|
||||||
|
*
|
||||||
|
* @return LogOptions The activity log options.
|
||||||
|
*/
|
||||||
|
public function getActivitylogOptions()
|
||||||
|
: LogOptions
|
||||||
|
{
|
||||||
|
return LogOptions::defaults()->logAll()->useLogName('User Management : ');
|
||||||
|
}
|
||||||
|
}
|
33
app/Models/Permission.php
Normal file
33
app/Models/Permission.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Models;
|
||||||
|
|
||||||
|
use Spatie\Activitylog\LogOptions;
|
||||||
|
use Spatie\Activitylog\Traits\LogsActivity;
|
||||||
|
use Spatie\Permission\Models\Permission as SpatiePermission;
|
||||||
|
|
||||||
|
class Permission extends SpatiePermission
|
||||||
|
{
|
||||||
|
use LogsActivity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the activity log options for this permission.
|
||||||
|
*
|
||||||
|
* @return LogOptions The activity log options.
|
||||||
|
*/
|
||||||
|
public function getActivitylogOptions()
|
||||||
|
: LogOptions
|
||||||
|
{
|
||||||
|
return LogOptions::defaults()->logAll()->useLogName('User Management|Permissions : ');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the permission group associated with this permission.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo The permission group relationship.
|
||||||
|
*/
|
||||||
|
public function group()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(PermissionGroup::class, 'permission_group_id');
|
||||||
|
}
|
||||||
|
}
|
60
app/Models/PermissionGroup.php
Normal file
60
app/Models/PermissionGroup.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Models;
|
||||||
|
|
||||||
|
use Spatie\Permission\Models\Role;
|
||||||
|
|
||||||
|
class PermissionGroup extends Base
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'slug'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all permissions associated with a given permission group ID.
|
||||||
|
*
|
||||||
|
* @param int $id The ID of the permission group.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Database\Eloquent\Collection The collection of permissions.
|
||||||
|
*/
|
||||||
|
public static function getpermissionsByGroupId($id)
|
||||||
|
{
|
||||||
|
return Permission::where('permission_group_id', $id)->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a relationship instance for the Permission model.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||||
|
*/
|
||||||
|
public function permission()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Permission::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the roles associated with a given permission group.
|
||||||
|
*
|
||||||
|
* @param object $group The permission group object.
|
||||||
|
*
|
||||||
|
* @return array The array of roles associated with the permission group.
|
||||||
|
*/
|
||||||
|
public function roles($group)
|
||||||
|
{
|
||||||
|
$permission = Permission::where('permission_group_id', $group->id)->first();
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
$roles = Role::all();
|
||||||
|
|
||||||
|
foreach ($roles as $role) {
|
||||||
|
if ($role->hasPermissionTo($permission->name)) {
|
||||||
|
array_push($data, $role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
app/Models/Role.php
Normal file
25
app/Models/Role.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
use Spatie\Activitylog\LogOptions;
|
||||||
|
use Spatie\Activitylog\Traits\LogsActivity;
|
||||||
|
use Spatie\Permission\Models\Role as SpatieRole;
|
||||||
|
|
||||||
|
class Role extends SpatieRole
|
||||||
|
{
|
||||||
|
use softDeletes, LogsActivity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the activity log options for this role.
|
||||||
|
*
|
||||||
|
* @return LogOptions The activity log options.
|
||||||
|
*/
|
||||||
|
public function getActivitylogOptions()
|
||||||
|
: LogOptions
|
||||||
|
{
|
||||||
|
return LogOptions::defaults()->logAll()->useLogName('User Management|Roles : ');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
73
app/Models/User.php
Normal file
73
app/Models/User.php
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
|
use Illuminate\Notifications\Notifiable;
|
||||||
|
use Spatie\Permission\Traits\HasRoles;
|
||||||
|
use Wildside\Userstamps\Userstamps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class User
|
||||||
|
*
|
||||||
|
* This class extends the Laravel's Authenticatable class and represents a User in the application.
|
||||||
|
* It includes traits for using factories, notifications, API tokens, and UUIDs.
|
||||||
|
*
|
||||||
|
* @property string $name The name of the user.
|
||||||
|
* @property string $email The email of the user.
|
||||||
|
* @property string $password The hashed password of the user.
|
||||||
|
* @property string $remember_token The token used for "remember me" functionality.
|
||||||
|
*
|
||||||
|
* @package App\Models
|
||||||
|
*/
|
||||||
|
class User extends Authenticatable
|
||||||
|
{
|
||||||
|
use Notifiable, Userstamps, HasRoles, softDeletes;
|
||||||
|
|
||||||
|
protected $guard_name = ['web'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*
|
||||||
|
* These are the attributes that can be set in bulk during a create or update operation.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'email',
|
||||||
|
'password',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that should be hidden for serialization.
|
||||||
|
*
|
||||||
|
* These are the attributes that will be hidden when the model is converted to an array or JSON.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $hidden = [
|
||||||
|
'password',
|
||||||
|
'remember_token',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the attributes that should be cast.
|
||||||
|
*
|
||||||
|
* This method defines how the attributes should be cast when accessed.
|
||||||
|
* In this case, 'email_verified_at' is cast to 'datetime', 'password' is cast to 'hashed', and 'id' is cast to 'string'.
|
||||||
|
*
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
protected function casts()
|
||||||
|
: array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'email_verified_at' => 'datetime',
|
||||||
|
'password' => 'hashed',
|
||||||
|
'id' => 'string',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
0
app/Providers/.gitkeep
Normal file
0
app/Providers/.gitkeep
Normal file
32
app/Providers/EventServiceProvider.php
Normal file
32
app/Providers/EventServiceProvider.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||||
|
|
||||||
|
class EventServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The event handler mappings for the application.
|
||||||
|
*
|
||||||
|
* @var array<string, array<int, string>>
|
||||||
|
*/
|
||||||
|
protected $listen = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if events should be discovered.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected static $shouldDiscoverEvents = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the proper event listeners for email verification.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function configureEmailVerification(): void
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
49
app/Providers/RouteServiceProvider.php
Normal file
49
app/Providers/RouteServiceProvider.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||||
|
|
||||||
|
class RouteServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Called before routes are registered.
|
||||||
|
*
|
||||||
|
* Register any model bindings or pattern based filters.
|
||||||
|
*/
|
||||||
|
public function boot(): void
|
||||||
|
{
|
||||||
|
parent::boot();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the routes for the application.
|
||||||
|
*/
|
||||||
|
public function map(): void
|
||||||
|
{
|
||||||
|
$this->mapApiRoutes();
|
||||||
|
|
||||||
|
$this->mapWebRoutes();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the "web" routes for the application.
|
||||||
|
*
|
||||||
|
* These routes all receive session state, CSRF protection, etc.
|
||||||
|
*/
|
||||||
|
protected function mapWebRoutes(): void
|
||||||
|
{
|
||||||
|
Route::middleware('web')->group(module_path('Usermanagement', '/routes/web.php'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the "api" routes for the application.
|
||||||
|
*
|
||||||
|
* These routes are typically stateless.
|
||||||
|
*/
|
||||||
|
protected function mapApiRoutes(): void
|
||||||
|
{
|
||||||
|
Route::middleware('api')->prefix('api')->name('api.')->group(module_path('Usermanagement', '/routes/api.php'));
|
||||||
|
}
|
||||||
|
}
|
124
app/Providers/UsermanagementServiceProvider.php
Normal file
124
app/Providers/UsermanagementServiceProvider.php
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Blade;
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
|
class UsermanagementServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
protected string $moduleName = 'Usermanagement';
|
||||||
|
|
||||||
|
protected string $moduleNameLower = 'usermanagement';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boot the application events.
|
||||||
|
*/
|
||||||
|
public function boot(): void
|
||||||
|
{
|
||||||
|
$this->registerCommands();
|
||||||
|
$this->registerCommandSchedules();
|
||||||
|
$this->registerTranslations();
|
||||||
|
$this->registerConfig();
|
||||||
|
$this->registerViews();
|
||||||
|
$this->loadMigrationsFrom(module_path($this->moduleName, 'database/migrations'));
|
||||||
|
|
||||||
|
if (class_exists('Breadcrumbs')) {
|
||||||
|
require __DIR__ . '/../../routes/breadcrumbs.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the service provider.
|
||||||
|
*/
|
||||||
|
public function register(): void
|
||||||
|
{
|
||||||
|
$this->app->register(EventServiceProvider::class);
|
||||||
|
$this->app->register(RouteServiceProvider::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register commands in the format of Command::class
|
||||||
|
*/
|
||||||
|
protected function registerCommands(): void
|
||||||
|
{
|
||||||
|
// $this->commands([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register command Schedules.
|
||||||
|
*/
|
||||||
|
protected function registerCommandSchedules(): void
|
||||||
|
{
|
||||||
|
// $this->app->booted(function () {
|
||||||
|
// $schedule = $this->app->make(Schedule::class);
|
||||||
|
// $schedule->command('inspire')->hourly();
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register translations.
|
||||||
|
*/
|
||||||
|
public function registerTranslations(): void
|
||||||
|
{
|
||||||
|
$langPath = resource_path('lang/modules/'.$this->moduleNameLower);
|
||||||
|
|
||||||
|
if (is_dir($langPath)) {
|
||||||
|
$this->loadTranslationsFrom($langPath, $this->moduleNameLower);
|
||||||
|
$this->loadJsonTranslationsFrom($langPath);
|
||||||
|
} else {
|
||||||
|
$this->loadTranslationsFrom(module_path($this->moduleName, 'lang'), $this->moduleNameLower);
|
||||||
|
$this->loadJsonTranslationsFrom(module_path($this->moduleName, 'lang'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register config.
|
||||||
|
*/
|
||||||
|
protected function registerConfig(): void
|
||||||
|
{
|
||||||
|
$this->publishes([module_path($this->moduleName, 'config/config.php') => config_path($this->moduleNameLower.'.php')], 'config');
|
||||||
|
$this->mergeConfigFrom(module_path($this->moduleName, 'config/config.php'), $this->moduleNameLower);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register views.
|
||||||
|
*/
|
||||||
|
public function registerViews(): void
|
||||||
|
{
|
||||||
|
$viewPath = resource_path('views/modules/'.$this->moduleNameLower);
|
||||||
|
$sourcePath = module_path($this->moduleName, 'resources/views');
|
||||||
|
|
||||||
|
$this->publishes([$sourcePath => $viewPath], ['views', $this->moduleNameLower.'-module-views']);
|
||||||
|
|
||||||
|
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->moduleNameLower);
|
||||||
|
|
||||||
|
$componentNamespace = str_replace('/', '\\', config('modules.namespace').'\\'.$this->moduleName.'\\'.ltrim(config('modules.paths.generator.component-class.path'), config('modules.paths.app_folder', '')));
|
||||||
|
Blade::componentNamespace($componentNamespace, $this->moduleNameLower);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the services provided by the provider.
|
||||||
|
*
|
||||||
|
* @return array<string>
|
||||||
|
*/
|
||||||
|
public function provides(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string>
|
||||||
|
*/
|
||||||
|
private function getPublishableViewPaths(): array
|
||||||
|
{
|
||||||
|
$paths = [];
|
||||||
|
foreach (config('view.paths') as $path) {
|
||||||
|
if (is_dir($path.'/modules/'.$this->moduleNameLower)) {
|
||||||
|
$paths[] = $path.'/modules/'.$this->moduleNameLower;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $paths;
|
||||||
|
}
|
||||||
|
}
|
30
composer.json
Normal file
30
composer.json
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"name": "putrakuningan/usermanagement",
|
||||||
|
"description": "",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Widart",
|
||||||
|
"email": "n.widart@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
],
|
||||||
|
"aliases": {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Modules\\Usermanagement\\": "app/",
|
||||||
|
"Modules\\Usermanagement\\Database\\Factories\\": "database/factories/",
|
||||||
|
"Modules\\Usermanagement\\Database\\Seeders\\": "database/seeders/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"Modules\\Usermanagement\\Tests\\": "tests/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
composer.lock
generated
Normal file
18
composer.lock
generated
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"_readme": [
|
||||||
|
"This file locks the dependencies of your project to a known state",
|
||||||
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
|
"This file is @generated automatically"
|
||||||
|
],
|
||||||
|
"content-hash": "2864198e9d1b1265f9eb249b3c2e2689",
|
||||||
|
"packages": [],
|
||||||
|
"packages-dev": [],
|
||||||
|
"aliases": [],
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"stability-flags": [],
|
||||||
|
"prefer-stable": false,
|
||||||
|
"prefer-lowest": false,
|
||||||
|
"platform": [],
|
||||||
|
"platform-dev": [],
|
||||||
|
"plugin-api-version": "2.6.0"
|
||||||
|
}
|
0
config/.gitkeep
Normal file
0
config/.gitkeep
Normal file
5
config/config.php
Normal file
5
config/config.php
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'name' => 'Usermanagement',
|
||||||
|
];
|
0
database/migrations/.gitkeep
Normal file
0
database/migrations/.gitkeep
Normal file
53
database/migrations/0001_01_01_000000_create_users_table.php
Normal file
53
database/migrations/0001_01_01_000000_create_users_table.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('users', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('email')->unique();
|
||||||
|
$table->timestamp('email_verified_at')->nullable();
|
||||||
|
$table->string('password');
|
||||||
|
$table->rememberToken();
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
$table->unsignedBigInteger('created_by')->nullable();
|
||||||
|
$table->unsignedBigInteger('updated_by')->nullable();
|
||||||
|
$table->unsignedBigInteger('deleted_by')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create('password_reset_tokens', function (Blueprint $table) {
|
||||||
|
$table->string('email')->primary();
|
||||||
|
$table->string('token');
|
||||||
|
$table->timestamp('created_at')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create('sessions', function (Blueprint $table) {
|
||||||
|
$table->string('id')->primary();
|
||||||
|
$table->foreignId('user_id')->nullable()->index();
|
||||||
|
$table->string('ip_address', 45)->nullable();
|
||||||
|
$table->text('user_agent')->nullable();
|
||||||
|
$table->longText('payload');
|
||||||
|
$table->integer('last_activity')->index();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('users');
|
||||||
|
Schema::dropIfExists('password_reset_tokens');
|
||||||
|
Schema::dropIfExists('sessions');
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$teams = config('permission.teams');
|
||||||
|
$tableNames = config('permission.table_names');
|
||||||
|
$columnNames = config('permission.column_names');
|
||||||
|
$pivotRole = $columnNames['role_pivot_key'] ?? 'role_id';
|
||||||
|
$pivotPermission = $columnNames['permission_pivot_key'] ?? 'permission_id';
|
||||||
|
|
||||||
|
if (empty($tableNames)) {
|
||||||
|
throw new \Exception('Error: config/permission.php not loaded. Run [php artisan config:clear] and try again.');
|
||||||
|
}
|
||||||
|
if ($teams && empty($columnNames['team_foreign_key'] ?? null)) {
|
||||||
|
throw new \Exception('Error: team_foreign_key on config/permission.php not loaded. Run [php artisan config:clear] and try again.');
|
||||||
|
}
|
||||||
|
|
||||||
|
Schema::create($tableNames['permissions'], function (Blueprint $table) {
|
||||||
|
//$table->engine('InnoDB');
|
||||||
|
$table->bigIncrements('id'); // permission id
|
||||||
|
$table->string('name'); // For MyISAM use string('name', 225); // (or 166 for InnoDB with Redundant/Compact row format)
|
||||||
|
$table->string('guard_name'); // For MyISAM use string('guard_name', 25);
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
$table->unique(['name', 'guard_name']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create($tableNames['roles'], function (Blueprint $table) use ($teams, $columnNames) {
|
||||||
|
//$table->engine('InnoDB');
|
||||||
|
$table->bigIncrements('id'); // role id
|
||||||
|
if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing
|
||||||
|
$table->unsignedBigInteger($columnNames['team_foreign_key'])->nullable();
|
||||||
|
$table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index');
|
||||||
|
}
|
||||||
|
$table->string('name'); // For MyISAM use string('name', 225); // (or 166 for InnoDB with Redundant/Compact row format)
|
||||||
|
$table->string('guard_name'); // For MyISAM use string('guard_name', 25);
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
if ($teams || config('permission.testing')) {
|
||||||
|
$table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']);
|
||||||
|
} else {
|
||||||
|
$table->unique(['name', 'guard_name']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create($tableNames['model_has_permissions'], function (Blueprint $table) use ($tableNames, $columnNames, $pivotPermission, $teams) {
|
||||||
|
$table->unsignedBigInteger($pivotPermission);
|
||||||
|
|
||||||
|
$table->string('model_type');
|
||||||
|
$table->unsignedBigInteger($columnNames['model_morph_key']);
|
||||||
|
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index');
|
||||||
|
|
||||||
|
$table->foreign($pivotPermission)
|
||||||
|
->references('id') // permission id
|
||||||
|
->on($tableNames['permissions'])
|
||||||
|
->onDelete('cascade');
|
||||||
|
if ($teams) {
|
||||||
|
$table->unsignedBigInteger($columnNames['team_foreign_key']);
|
||||||
|
$table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index');
|
||||||
|
|
||||||
|
$table->primary([$columnNames['team_foreign_key'], $pivotPermission, $columnNames['model_morph_key'], 'model_type'],
|
||||||
|
'model_has_permissions_permission_model_type_primary');
|
||||||
|
} else {
|
||||||
|
$table->primary([$pivotPermission, $columnNames['model_morph_key'], 'model_type'],
|
||||||
|
'model_has_permissions_permission_model_type_primary');
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create($tableNames['model_has_roles'], function (Blueprint $table) use ($tableNames, $columnNames, $pivotRole, $teams) {
|
||||||
|
$table->unsignedBigInteger($pivotRole);
|
||||||
|
|
||||||
|
$table->string('model_type');
|
||||||
|
$table->unsignedBigInteger($columnNames['model_morph_key']);
|
||||||
|
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index');
|
||||||
|
|
||||||
|
$table->foreign($pivotRole)
|
||||||
|
->references('id') // role id
|
||||||
|
->on($tableNames['roles'])
|
||||||
|
->onDelete('cascade');
|
||||||
|
if ($teams) {
|
||||||
|
$table->unsignedBigInteger($columnNames['team_foreign_key']);
|
||||||
|
$table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index');
|
||||||
|
|
||||||
|
$table->primary([$columnNames['team_foreign_key'], $pivotRole, $columnNames['model_morph_key'], 'model_type'],
|
||||||
|
'model_has_roles_role_model_type_primary');
|
||||||
|
} else {
|
||||||
|
$table->primary([$pivotRole, $columnNames['model_morph_key'], 'model_type'],
|
||||||
|
'model_has_roles_role_model_type_primary');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create($tableNames['role_has_permissions'], function (Blueprint $table) use ($tableNames, $pivotRole, $pivotPermission) {
|
||||||
|
$table->unsignedBigInteger($pivotPermission);
|
||||||
|
$table->unsignedBigInteger($pivotRole);
|
||||||
|
|
||||||
|
$table->foreign($pivotPermission)
|
||||||
|
->references('id') // permission id
|
||||||
|
->on($tableNames['permissions'])
|
||||||
|
->onDelete('cascade');
|
||||||
|
|
||||||
|
$table->foreign($pivotRole)
|
||||||
|
->references('id') // role id
|
||||||
|
->on($tableNames['roles'])
|
||||||
|
->onDelete('cascade');
|
||||||
|
|
||||||
|
$table->primary([$pivotPermission, $pivotRole], 'role_has_permissions_permission_id_role_id_primary');
|
||||||
|
});
|
||||||
|
|
||||||
|
app('cache')
|
||||||
|
->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null)
|
||||||
|
->forget(config('permission.cache.key'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$tableNames = config('permission.table_names');
|
||||||
|
|
||||||
|
if (empty($tableNames)) {
|
||||||
|
throw new \Exception('Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.');
|
||||||
|
}
|
||||||
|
|
||||||
|
Schema::drop($tableNames['role_has_permissions']);
|
||||||
|
Schema::drop($tableNames['model_has_roles']);
|
||||||
|
Schema::drop($tableNames['model_has_permissions']);
|
||||||
|
Schema::drop($tableNames['roles']);
|
||||||
|
Schema::drop($tableNames['permissions']);
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('permission_groups', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('slug');
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
|
||||||
|
$table->unsignedBigInteger('created_by')->nullable();
|
||||||
|
$table->unsignedBigInteger('updated_by')->nullable();
|
||||||
|
$table->unsignedBigInteger('deleted_by')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('permission_groups');
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Modules\Usermanagement\Models\PermissionGroup;
|
||||||
|
|
||||||
|
return new class extends Migration {
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
: void
|
||||||
|
{
|
||||||
|
Schema::table('permissions', function ($table) {
|
||||||
|
$table->string('module')->after('id')->nullable();
|
||||||
|
$table->foreignIdFor(PermissionGroup::class);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
: void
|
||||||
|
{
|
||||||
|
Schema::withoutForeignKeyConstraints(function () {
|
||||||
|
Schema::table('permissions', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('module');
|
||||||
|
$table->dropColumn('permission_group_id');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
32
database/migrations/2024_07_31_023136_update_users_table.php
Normal file
32
database/migrations/2024_07_31_023136_update_users_table.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->string('profile_photo_path', 2048)->nullable()->after('email');
|
||||||
|
$table->datetime('last_login_at')->nullable();
|
||||||
|
$table->string('last_login_ip')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('profile_photo_path');
|
||||||
|
$table->dropColumn('last_login_at');
|
||||||
|
$table->dropColumn('last_login_ip');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
0
database/seeders/.gitkeep
Normal file
0
database/seeders/.gitkeep
Normal file
16
database/seeders/UsermanagementDatabaseSeeder.php
Normal file
16
database/seeders/UsermanagementDatabaseSeeder.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Usermanagement\Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class UsermanagementDatabaseSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
// $this->call([]);
|
||||||
|
}
|
||||||
|
}
|
53
module.json
Normal file
53
module.json
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"name": "Usermanagement",
|
||||||
|
"alias": "usermanagement",
|
||||||
|
"database": "",
|
||||||
|
"description": "",
|
||||||
|
"keywords": [],
|
||||||
|
"priority": 0,
|
||||||
|
"providers": [
|
||||||
|
"Modules\\Usermanagement\\Providers\\UsermanagementServiceProvider"
|
||||||
|
],
|
||||||
|
"files": [],
|
||||||
|
"menu": {
|
||||||
|
"main": [],
|
||||||
|
"master": [],
|
||||||
|
"system": [
|
||||||
|
{
|
||||||
|
"title": "User Management",
|
||||||
|
"path": "users",
|
||||||
|
"icon": "ki-filled ki-users text-lg",
|
||||||
|
"classes": "",
|
||||||
|
"attributes": [],
|
||||||
|
"permission": "",
|
||||||
|
"roles": [],
|
||||||
|
"sub": [
|
||||||
|
{
|
||||||
|
"title": "Users",
|
||||||
|
"path": "users",
|
||||||
|
"classes": "",
|
||||||
|
"attributes": [],
|
||||||
|
"permission": "",
|
||||||
|
"roles": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Roles",
|
||||||
|
"path": "users.roles",
|
||||||
|
"classes": "",
|
||||||
|
"attributes": [],
|
||||||
|
"permission": "",
|
||||||
|
"roles": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Permissions",
|
||||||
|
"path": "users.permissions",
|
||||||
|
"classes": "",
|
||||||
|
"attributes": [],
|
||||||
|
"permission": "",
|
||||||
|
"roles": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
15
package.json
Normal file
15
package.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"axios": "^1.1.2",
|
||||||
|
"laravel-vite-plugin": "^0.7.5",
|
||||||
|
"sass": "^1.69.5",
|
||||||
|
"postcss": "^8.3.7",
|
||||||
|
"vite": "^4.0.0"
|
||||||
|
}
|
||||||
|
}
|
0
resources/assets/.gitkeep
Normal file
0
resources/assets/.gitkeep
Normal file
0
resources/assets/js/app.js
Normal file
0
resources/assets/js/app.js
Normal file
4
resources/assets/sass/app.scss
Normal file
4
resources/assets/sass/app.scss
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.login{
|
||||||
|
margin-top: 100px;
|
||||||
|
margin-bottom: 100px;
|
||||||
|
}
|
0
resources/views/.gitkeep
Normal file
0
resources/views/.gitkeep
Normal file
48
resources/views/roles/create.blade.php
Normal file
48
resources/views/roles/create.blade.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
@extends('layouts.main')
|
||||||
|
|
||||||
|
@section('breadcrumbs')
|
||||||
|
{{ Breadcrumbs::render(request()->route()->getName()) }}
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto">
|
||||||
|
@if(isset($role->id))
|
||||||
|
<form action="{{ route('users.roles.update', $role->id) }}" method="POST">
|
||||||
|
<input type="hidden" name="id" value="{{ $role->id }}">
|
||||||
|
@method('PUT')
|
||||||
|
@else
|
||||||
|
<form method="POST" action="{{ route('users.roles.store') }}">
|
||||||
|
@endif
|
||||||
|
@csrf
|
||||||
|
<div class="card pb-2.5">
|
||||||
|
<div class="card-header" id="basic_settings">
|
||||||
|
<h3 class="card-title">
|
||||||
|
{{ isset($role->id) ? 'Edit' : 'Add' }} Role
|
||||||
|
</h3>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<a href="{{ route('users.roles.index') }}" class="btn btn-xs btn-info">Back</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body grid gap-5">
|
||||||
|
|
||||||
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label class="form-label max-w-56">
|
||||||
|
Name
|
||||||
|
</label>
|
||||||
|
<div class="flex flex-wrap items-baseline w-full">
|
||||||
|
<input class="input @error('name') border-danger @enderror" type="text" name="name" value="{{ $role->name ?? '' }}">
|
||||||
|
@error('name')
|
||||||
|
<em class="alert text-danger text-sm">{{ $message }}</em>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
@endsection
|
165
resources/views/roles/index.blade.php
Normal file
165
resources/views/roles/index.blade.php
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
@extends('layouts.main')
|
||||||
|
|
||||||
|
@section('breadcrumbs')
|
||||||
|
{{ Breadcrumbs::render('users.roles') }}
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="grid">
|
||||||
|
<div class="card card-grid min-w-full" data-datatable="false" data-datatable-page-size="5" data-datatable-state-save="true" id="roles-table" data-api-url="{{ route('users.roles.datatables') }}">
|
||||||
|
<div class="card-header py-5 flex-wrap">
|
||||||
|
<h3 class="card-title">
|
||||||
|
List of Roles
|
||||||
|
</h3>
|
||||||
|
<div class="flex flex-wrap gap-2 lg:gap-5">
|
||||||
|
<div class="flex">
|
||||||
|
<label class="input input-sm"> <i class="ki-filled ki-magnifier"> </i>
|
||||||
|
<input placeholder="Search roles" id="search" type="text" value="">
|
||||||
|
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-wrap gap-2.5">
|
||||||
|
<select class="select select-sm w-28">
|
||||||
|
<option value="1">
|
||||||
|
Active
|
||||||
|
</option>
|
||||||
|
<option value="2">
|
||||||
|
Disabled
|
||||||
|
</option>
|
||||||
|
<option value="2">
|
||||||
|
Pending
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<select class="select select-sm w-28">
|
||||||
|
<option value="desc">
|
||||||
|
Latest
|
||||||
|
</option>
|
||||||
|
<option value="asc">
|
||||||
|
Oldest
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<button class="btn btn-sm btn-outline btn-primary">
|
||||||
|
<i class="ki-filled ki-setting-4"> </i> <Filters></Filters>
|
||||||
|
</button>
|
||||||
|
<div class="h-[24px] border border-r-gray-200"> </div>
|
||||||
|
<a class="btn btn-sm btn-light" href="{{ route('users.roles.export') }}"> Export to Excel </a>
|
||||||
|
<a class="btn btn-sm btn-primary" href="{{ route('users.roles.create') }}"> Add Role </a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="scrollable-x-auto">
|
||||||
|
<table class="table table-auto table-border align-middle text-gray-700 font-medium text-sm" data-datatable-table="true">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="w-14">
|
||||||
|
<input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox"/>
|
||||||
|
</th>
|
||||||
|
<th class="min-w-[250px]" data-datatable-column="name">
|
||||||
|
<span class="sort"> <span class="sort-label"> Role </span>
|
||||||
|
<span class="sort-icon"> </span> </span>
|
||||||
|
</th>
|
||||||
|
<th class="min-w-[50px] text-center" data-datatable-column="actions">Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer justify-center md:justify-between flex-col md:flex-row gap-3 text-gray-600 text-2sm font-medium">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
Show
|
||||||
|
<select class="select select-sm w-16" data-datatable-size="true" name="perpage"> </select> per page
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<span data-datatable-info="true"> </span>
|
||||||
|
<div class="pagination" data-datatable-pagination="true">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function deleteData(data) {
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Are you sure?',
|
||||||
|
text: "You won't be able to revert this!" + data,
|
||||||
|
icon: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: '#3085d6',
|
||||||
|
cancelButtonColor: '#d33',
|
||||||
|
confirmButtonText: 'Yes, delete it!'
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
$.ajaxSetup({
|
||||||
|
headers: {
|
||||||
|
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.ajax(`roles/${data}`, {
|
||||||
|
type: 'DELETE'
|
||||||
|
}).then((response) => {
|
||||||
|
swal.fire('Deleted!', 'User has been deleted.','success').then(() => {
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
Swal.fire('Error!', 'An error occurred while deleting the file.', 'error');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script type="module">
|
||||||
|
const element = document.querySelector('#roles-table');
|
||||||
|
const searchInput = document.getElementById('search');
|
||||||
|
|
||||||
|
const apiUrl = element.getAttribute('data-api-url');
|
||||||
|
const dataTableOptions = {
|
||||||
|
apiEndpoint: apiUrl,
|
||||||
|
pageSize: 5,
|
||||||
|
columns: {
|
||||||
|
select: {
|
||||||
|
render: (item, data, context) => {
|
||||||
|
const checkbox = document.createElement('input');
|
||||||
|
checkbox.className = 'checkbox checkbox-sm';
|
||||||
|
checkbox.type = 'checkbox';
|
||||||
|
checkbox.value = data.id.toString();
|
||||||
|
checkbox.setAttribute('data-datatable-row-check', 'true');
|
||||||
|
return checkbox.outerHTML.trim();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
title: 'Role',
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
title: 'Status',
|
||||||
|
render: (item, data) => {
|
||||||
|
return `<div class="flex flex-nowrap justify-center">
|
||||||
|
<a class="btn btn-sm btn-icon btn-clear btn-info" href="roles/${data.id}/edit">
|
||||||
|
<i class="ki-outline ki-notepad-edit"></i>
|
||||||
|
</a>
|
||||||
|
<a onclick="deleteData(${data.id})" class="delete btn btn-sm btn-icon btn-clear btn-danger">
|
||||||
|
<i class="ki-outline ki-trash"></i>
|
||||||
|
</a>
|
||||||
|
</div>`;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let dataTable = new KTDataTable(element, dataTableOptions);
|
||||||
|
// Custom search functionality
|
||||||
|
searchInput.addEventListener('input', function () {
|
||||||
|
const searchValue = this.value.trim();
|
||||||
|
dataTable.search(searchValue, true);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
|
|
100
resources/views/users/create.blade.php
Normal file
100
resources/views/users/create.blade.php
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
@extends('layouts.main')
|
||||||
|
|
||||||
|
@section('breadcrumbs')
|
||||||
|
{{ Breadcrumbs::render(request()->route()->getName()) }}
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto">
|
||||||
|
@if(isset($user->id))
|
||||||
|
<form action="{{ route('users.update', $user->id) }}" method="POST">
|
||||||
|
<input type="hidden" name="id" value="{{ $user->id }}">
|
||||||
|
@method('PUT')
|
||||||
|
@else
|
||||||
|
<form method="POST" action="{{ route('users.store') }}">
|
||||||
|
@endif
|
||||||
|
@csrf
|
||||||
|
<div class="card pb-2.5">
|
||||||
|
<div class="card-header" id="basic_settings">
|
||||||
|
<h3 class="card-title">
|
||||||
|
{{ isset($user->id) ? 'Edit' : 'Add' }} User
|
||||||
|
</h3>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<label class="switch switch-sm">
|
||||||
|
<span class="switch-label">
|
||||||
|
Public Profile
|
||||||
|
</span>
|
||||||
|
<input checked="" name="check" type="checkbox" value="1">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body grid gap-5">
|
||||||
|
|
||||||
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label class="form-label max-w-56">
|
||||||
|
Name
|
||||||
|
</label>
|
||||||
|
<div class="flex flex-wrap items-baseline w-full">
|
||||||
|
<input class="input @error('name') border-danger @enderror" type="text" name="name" value="{{ $user->name ?? '' }}">
|
||||||
|
@error('name')
|
||||||
|
<em class="alert text-danger text-sm">{{ $message }}</em>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label class="form-label max-w-56">
|
||||||
|
Email
|
||||||
|
</label>
|
||||||
|
<div class="flex flex-wrap items-baseline w-full">
|
||||||
|
<input class="w-full input @error('email') border-danger @enderror" type="email" name="email" value="{{ $user->email ?? '' }}">
|
||||||
|
@error('email')
|
||||||
|
<em class="alert text-danger text-sm">{{ $message }}</em>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label class="form-label max-w-56">
|
||||||
|
Password
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="flex flex-wrap items-baseline w-full">
|
||||||
|
<div class="input @error('password') border-danger @enderror" data-toggle-password="true" data-toggle-password-permanent="true">
|
||||||
|
<input placeholder="Password" type="password" name="password"/>
|
||||||
|
<div class="btn btn-icon" data-toggle-password-trigger="true">
|
||||||
|
<i class="ki-outline ki-eye toggle-password-active:hidden"></i>
|
||||||
|
<i class="ki-outline ki-eye-slash hidden toggle-password-active:block"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@error('password')
|
||||||
|
<em class="alert text-danger text-sm">{{ $message }}</em>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label class="form-label max-w-56">
|
||||||
|
Password Confirmation
|
||||||
|
</label>
|
||||||
|
<div class="flex flex-wrap items-baseline w-full">
|
||||||
|
<div class="input @error('password_confirmation') border-danger @enderror" data-toggle-password="true" data-toggle-password-permanent="true">
|
||||||
|
<input placeholder="Password Confirmation" type="password" name="password_confirmation"/>
|
||||||
|
<div class="btn btn-icon" data-toggle-password-trigger="true">
|
||||||
|
<i class="ki-outline ki-eye toggle-password-active:hidden"></i>
|
||||||
|
<i class="ki-outline ki-eye-slash hidden toggle-password-active:block"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@error('password_confirmation')
|
||||||
|
<em class="alert text-danger text-sm">{{ $message }}</em>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
@endsection
|
172
resources/views/users/index.blade.php
Normal file
172
resources/views/users/index.blade.php
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
@extends('layouts.main')
|
||||||
|
|
||||||
|
@section('breadcrumbs')
|
||||||
|
{{ Breadcrumbs::render('users') }}
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="grid">
|
||||||
|
<div class="card card-grid min-w-full" data-datatable="false" data-datatable-page-size="5" data-datatable-state-save="true" id="users-table" data-api-url="{{ route('users.datatables') }}">
|
||||||
|
<div class="card-header py-5 flex-wrap">
|
||||||
|
<h3 class="card-title">
|
||||||
|
List of Users
|
||||||
|
</h3>
|
||||||
|
<div class="flex flex-wrap gap-2 lg:gap-5">
|
||||||
|
<div class="flex">
|
||||||
|
<label class="input input-sm"> <i class="ki-filled ki-magnifier"> </i>
|
||||||
|
<input placeholder="Search users" id="search" type="text" value="">
|
||||||
|
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-wrap gap-2.5">
|
||||||
|
<select class="select select-sm w-28">
|
||||||
|
<option value="1">
|
||||||
|
Active
|
||||||
|
</option>
|
||||||
|
<option value="2">
|
||||||
|
Disabled
|
||||||
|
</option>
|
||||||
|
<option value="2">
|
||||||
|
Pending
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<select class="select select-sm w-28">
|
||||||
|
<option value="desc">
|
||||||
|
Latest
|
||||||
|
</option>
|
||||||
|
<option value="asc">
|
||||||
|
Oldest
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<button class="btn btn-sm btn-outline btn-primary">
|
||||||
|
<i class="ki-filled ki-setting-4"> </i> Filters
|
||||||
|
</button>
|
||||||
|
<div class="h-[24px] border border-r-gray-200"> </div>
|
||||||
|
<a class="btn btn-sm btn-light" href="{{ route('users.export') }}"> Export to Excel </a>
|
||||||
|
<a class="btn btn-sm btn-primary" href="{{ route('users.create') }}"> Add User </a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="scrollable-x-auto">
|
||||||
|
<table class="table table-auto table-border align-middle text-gray-700 font-medium text-sm" data-datatable-table="true">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="w-14">
|
||||||
|
<input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox"/>
|
||||||
|
</th>
|
||||||
|
<th class="min-w-[250px]" data-datatable-column="name">
|
||||||
|
<span class="sort"> <span class="sort-label"> Name </span>
|
||||||
|
<span class="sort-icon"> </span> </span>
|
||||||
|
</th>
|
||||||
|
<th class="min-w-[185px]" data-datatable-column="email">
|
||||||
|
<span class="sort"> <span class="sort-label"> Email </span>
|
||||||
|
<span class="sort-icon"> </span> </span>
|
||||||
|
</th>
|
||||||
|
<th class="min-w-[50px] text-center" data-datatable-column="actions">Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer justify-center md:justify-between flex-col md:flex-row gap-3 text-gray-600 text-2sm font-medium">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
Show
|
||||||
|
<select class="select select-sm w-16" data-datatable-size="true" name="perpage"> </select> per page
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<span data-datatable-info="true"> </span>
|
||||||
|
<div class="pagination" data-datatable-pagination="true">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function deleteData(data) {
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Are you sure?',
|
||||||
|
text: "You won't be able to revert this!" + data,
|
||||||
|
icon: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: '#3085d6',
|
||||||
|
cancelButtonColor: '#d33',
|
||||||
|
confirmButtonText: 'Yes, delete it!'
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
$.ajaxSetup({
|
||||||
|
headers: {
|
||||||
|
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.ajax(`users/${data}`, {
|
||||||
|
type: 'DELETE'
|
||||||
|
}).then((response) => {
|
||||||
|
swal.fire('Deleted!', 'User has been deleted.','success').then(() => {
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
Swal.fire('Error!', 'An error occurred while deleting the file.', 'error');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script type="module">
|
||||||
|
const element = document.querySelector('#users-table');
|
||||||
|
const searchInput = document.getElementById('search');
|
||||||
|
|
||||||
|
const apiUrl = element.getAttribute('data-api-url');
|
||||||
|
const dataTableOptions = {
|
||||||
|
apiEndpoint: apiUrl,
|
||||||
|
pageSize: 5,
|
||||||
|
columns: {
|
||||||
|
select: {
|
||||||
|
render: (item, data, context) => {
|
||||||
|
const checkbox = document.createElement('input');
|
||||||
|
checkbox.className = 'checkbox checkbox-sm';
|
||||||
|
checkbox.type = 'checkbox';
|
||||||
|
checkbox.value = data.id.toString();
|
||||||
|
checkbox.setAttribute('data-datatable-row-check', 'true');
|
||||||
|
return checkbox.outerHTML.trim();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
title: 'Name',
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
title: 'Email',
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
title: 'Status',
|
||||||
|
render: (item, data) => {
|
||||||
|
return `<div class="flex flex-nowrap justify-center">
|
||||||
|
<a class="btn btn-sm btn-icon btn-clear btn-info" href="users/${data.id}/edit">
|
||||||
|
<i class="ki-outline ki-notepad-edit"></i>
|
||||||
|
</a>
|
||||||
|
<a onclick="deleteData(${data.id})" class="delete btn btn-sm btn-icon btn-clear btn-danger">
|
||||||
|
<i class="ki-outline ki-trash"></i>
|
||||||
|
</a>
|
||||||
|
</div>`;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let dataTable = new KTDataTable(element, dataTableOptions);
|
||||||
|
// Custom search functionality
|
||||||
|
searchInput.addEventListener('input', function () {
|
||||||
|
const searchValue = this.value.trim();
|
||||||
|
dataTable.search(searchValue, true);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
|
|
0
routes/.gitkeep
Normal file
0
routes/.gitkeep
Normal file
1
routes/api.php
Normal file
1
routes/api.php
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?php
|
34
routes/breadcrumbs.php
Normal file
34
routes/breadcrumbs.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Diglactic\Breadcrumbs\Breadcrumbs;
|
||||||
|
use Diglactic\Breadcrumbs\Generator as BreadcrumbTrail;
|
||||||
|
|
||||||
|
// Home
|
||||||
|
Breadcrumbs::for('users', function (BreadcrumbTrail $trail) {
|
||||||
|
$trail->push('Users', route('users.index'));
|
||||||
|
});
|
||||||
|
|
||||||
|
Breadcrumbs::for('users.create', function (BreadcrumbTrail $trail) {
|
||||||
|
$trail->parent('users');
|
||||||
|
$trail->push('Add User', route('users.create'));
|
||||||
|
});
|
||||||
|
|
||||||
|
Breadcrumbs::for('users.edit', function (BreadcrumbTrail $trail) {
|
||||||
|
$trail->parent('users');
|
||||||
|
$trail->push('Edit User');
|
||||||
|
});
|
||||||
|
|
||||||
|
Breadcrumbs::for('users.roles', function (BreadcrumbTrail $trail) {
|
||||||
|
$trail->parent('users');
|
||||||
|
$trail->push('Roles', route('users.roles.index'));
|
||||||
|
});
|
||||||
|
|
||||||
|
Breadcrumbs::for('users.roles.create', function (BreadcrumbTrail $trail) {
|
||||||
|
$trail->parent('users.roles');
|
||||||
|
$trail->push('Add Role', route('users.roles.create'));
|
||||||
|
});
|
||||||
|
|
||||||
|
Breadcrumbs::for('users.roles.edit', function (BreadcrumbTrail $trail) {
|
||||||
|
$trail->parent('users.roles');
|
||||||
|
$trail->push('Edit Role');
|
||||||
|
});
|
43
routes/web.php
Normal file
43
routes/web.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use Modules\Usermanagement\Http\Controllers\PermissionsController;
|
||||||
|
use Modules\Usermanagement\Http\Controllers\RolesController;
|
||||||
|
use Modules\Usermanagement\Http\Controllers\UsersController;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Web Routes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here is where you can register web routes for your application. These
|
||||||
|
| routes are loaded by the RouteServiceProvider within a group which
|
||||||
|
| contains the "web" middleware group. Now create something great!
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
//Route::middleware(['auth'])->group(function () {
|
||||||
|
|
||||||
|
Route::name('users.')->prefix('users')->group(function () {
|
||||||
|
Route::get('restore/{id}', [UsersController::class,'restore'])->name('restore');
|
||||||
|
Route::get('datatables', [UsersController::class, 'dataForDatatables'])->name('datatables');
|
||||||
|
Route::get('export', [UsersController::class, 'export'])->name('export');
|
||||||
|
});
|
||||||
|
Route::resource('users', UsersController::class);
|
||||||
|
|
||||||
|
Route::name('users.')->group(function () {
|
||||||
|
Route::name('roles.')->prefix('roles')->group(function () {
|
||||||
|
Route::get('restore/{id}', [RolesController::class,'restore'])->name('restore');
|
||||||
|
Route::get('datatables', [RolesController::class, 'dataForDatatables'])->name('datatables');
|
||||||
|
Route::get('export', [RolesController ::class, 'export'])->name('export');
|
||||||
|
});
|
||||||
|
Route::resource('roles', RolesController::class);
|
||||||
|
|
||||||
|
Route::resource('permissions', PermissionsController::class);
|
||||||
|
Route::name('permissions.')->prefix('permissions')->group(function () {
|
||||||
|
Route::get('restore/{id}', [PermissionsController::class,'restore'])->name('restore');
|
||||||
|
Route::get('datatables', [PermissionsController::class, 'dataForDatatables'])->name('datatables');
|
||||||
|
Route::get('export', [PermissionsController ::class, 'export'])->name('export');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
//});
|
||||||
|
|
0
tests/Feature/.gitkeep
Normal file
0
tests/Feature/.gitkeep
Normal file
0
tests/Unit/.gitkeep
Normal file
0
tests/Unit/.gitkeep
Normal file
25
vendor/autoload.php
vendored
Normal file
25
vendor/autoload.php
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload.php @generated by Composer
|
||||||
|
|
||||||
|
if (PHP_VERSION_ID < 50600) {
|
||||||
|
if (!headers_sent()) {
|
||||||
|
header('HTTP/1.1 500 Internal Server Error');
|
||||||
|
}
|
||||||
|
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||||
|
if (!ini_get('display_errors')) {
|
||||||
|
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||||
|
fwrite(STDERR, $err);
|
||||||
|
} elseif (!headers_sent()) {
|
||||||
|
echo $err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trigger_error(
|
||||||
|
$err,
|
||||||
|
E_USER_ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__ . '/composer/autoload_real.php';
|
||||||
|
|
||||||
|
return ComposerAutoloaderInit2864198e9d1b1265f9eb249b3c2e2689::getLoader();
|
579
vendor/composer/ClassLoader.php
vendored
Normal file
579
vendor/composer/ClassLoader.php
vendored
Normal file
@ -0,0 +1,579 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||||
|
*
|
||||||
|
* $loader = new \Composer\Autoload\ClassLoader();
|
||||||
|
*
|
||||||
|
* // register classes with namespaces
|
||||||
|
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||||
|
* $loader->add('Symfony', __DIR__.'/framework');
|
||||||
|
*
|
||||||
|
* // activate the autoloader
|
||||||
|
* $loader->register();
|
||||||
|
*
|
||||||
|
* // to enable searching the include path (eg. for PEAR packages)
|
||||||
|
* $loader->setUseIncludePath(true);
|
||||||
|
*
|
||||||
|
* In this example, if you try to use a class in the Symfony\Component
|
||||||
|
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||||
|
* the autoloader will first look for the class under the component/
|
||||||
|
* directory, and it will then fallback to the framework/ directory if not
|
||||||
|
* found before giving up.
|
||||||
|
*
|
||||||
|
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
* @see https://www.php-fig.org/psr/psr-0/
|
||||||
|
* @see https://www.php-fig.org/psr/psr-4/
|
||||||
|
*/
|
||||||
|
class ClassLoader
|
||||||
|
{
|
||||||
|
/** @var \Closure(string):void */
|
||||||
|
private static $includeFile;
|
||||||
|
|
||||||
|
/** @var string|null */
|
||||||
|
private $vendorDir;
|
||||||
|
|
||||||
|
// PSR-4
|
||||||
|
/**
|
||||||
|
* @var array<string, array<string, int>>
|
||||||
|
*/
|
||||||
|
private $prefixLengthsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var array<string, list<string>>
|
||||||
|
*/
|
||||||
|
private $prefixDirsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var list<string>
|
||||||
|
*/
|
||||||
|
private $fallbackDirsPsr4 = array();
|
||||||
|
|
||||||
|
// PSR-0
|
||||||
|
/**
|
||||||
|
* List of PSR-0 prefixes
|
||||||
|
*
|
||||||
|
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
|
||||||
|
*
|
||||||
|
* @var array<string, array<string, list<string>>>
|
||||||
|
*/
|
||||||
|
private $prefixesPsr0 = array();
|
||||||
|
/**
|
||||||
|
* @var list<string>
|
||||||
|
*/
|
||||||
|
private $fallbackDirsPsr0 = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $useIncludePath = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, string>
|
||||||
|
*/
|
||||||
|
private $classMap = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $classMapAuthoritative = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, bool>
|
||||||
|
*/
|
||||||
|
private $missingClasses = array();
|
||||||
|
|
||||||
|
/** @var string|null */
|
||||||
|
private $apcuPrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, self>
|
||||||
|
*/
|
||||||
|
private static $registeredLoaders = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|null $vendorDir
|
||||||
|
*/
|
||||||
|
public function __construct($vendorDir = null)
|
||||||
|
{
|
||||||
|
$this->vendorDir = $vendorDir;
|
||||||
|
self::initializeIncludeClosure();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, list<string>>
|
||||||
|
*/
|
||||||
|
public function getPrefixes()
|
||||||
|
{
|
||||||
|
if (!empty($this->prefixesPsr0)) {
|
||||||
|
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, list<string>>
|
||||||
|
*/
|
||||||
|
public function getPrefixesPsr4()
|
||||||
|
{
|
||||||
|
return $this->prefixDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list<string>
|
||||||
|
*/
|
||||||
|
public function getFallbackDirs()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list<string>
|
||||||
|
*/
|
||||||
|
public function getFallbackDirsPsr4()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, string> Array of classname => path
|
||||||
|
*/
|
||||||
|
public function getClassMap()
|
||||||
|
{
|
||||||
|
return $this->classMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, string> $classMap Class to filename map
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addClassMap(array $classMap)
|
||||||
|
{
|
||||||
|
if ($this->classMap) {
|
||||||
|
$this->classMap = array_merge($this->classMap, $classMap);
|
||||||
|
} else {
|
||||||
|
$this->classMap = $classMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-0 directories for a given prefix, either
|
||||||
|
* appending or prepending to the ones previously set for this prefix.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix
|
||||||
|
* @param list<string>|string $paths The PSR-0 root directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function add($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
$paths = (array) $paths;
|
||||||
|
if (!$prefix) {
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->fallbackDirsPsr0
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
$this->fallbackDirsPsr0,
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$first = $prefix[0];
|
||||||
|
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = $paths;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($prepend) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->prefixesPsr0[$first][$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
$this->prefixesPsr0[$first][$prefix],
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-4 directories for a given namespace, either
|
||||||
|
* appending or prepending to the ones previously set for this namespace.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
|
* @param list<string>|string $paths The PSR-4 base directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addPsr4($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
$paths = (array) $paths;
|
||||||
|
if (!$prefix) {
|
||||||
|
// Register directories for the root namespace.
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->fallbackDirsPsr4
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
$this->fallbackDirsPsr4,
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||||
|
// Register directories for a new namespace.
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
|
}
|
||||||
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
$this->prefixDirsPsr4[$prefix] = $paths;
|
||||||
|
} elseif ($prepend) {
|
||||||
|
// Prepend directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->prefixDirsPsr4[$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Append directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
$this->prefixDirsPsr4[$prefix],
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-0 directories for a given prefix,
|
||||||
|
* replacing any others previously set for this prefix.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix
|
||||||
|
* @param list<string>|string $paths The PSR-0 base directories
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function set($prefix, $paths)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
$this->fallbackDirsPsr0 = (array) $paths;
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-4 directories for a given namespace,
|
||||||
|
* replacing any others previously set for this namespace.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
|
* @param list<string>|string $paths The PSR-4 base directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setPsr4($prefix, $paths)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
$this->fallbackDirsPsr4 = (array) $paths;
|
||||||
|
} else {
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
|
}
|
||||||
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns on searching the include path for class files.
|
||||||
|
*
|
||||||
|
* @param bool $useIncludePath
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setUseIncludePath($useIncludePath)
|
||||||
|
{
|
||||||
|
$this->useIncludePath = $useIncludePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be used to check if the autoloader uses the include path to check
|
||||||
|
* for classes.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getUseIncludePath()
|
||||||
|
{
|
||||||
|
return $this->useIncludePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns off searching the prefix and fallback directories for classes
|
||||||
|
* that have not been registered with the class map.
|
||||||
|
*
|
||||||
|
* @param bool $classMapAuthoritative
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||||
|
{
|
||||||
|
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should class lookup fail if not found in the current class map?
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isClassMapAuthoritative()
|
||||||
|
{
|
||||||
|
return $this->classMapAuthoritative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||||
|
*
|
||||||
|
* @param string|null $apcuPrefix
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setApcuPrefix($apcuPrefix)
|
||||||
|
{
|
||||||
|
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getApcuPrefix()
|
||||||
|
{
|
||||||
|
return $this->apcuPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers this instance as an autoloader.
|
||||||
|
*
|
||||||
|
* @param bool $prepend Whether to prepend the autoloader or not
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register($prepend = false)
|
||||||
|
{
|
||||||
|
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||||
|
|
||||||
|
if (null === $this->vendorDir) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($prepend) {
|
||||||
|
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||||
|
} else {
|
||||||
|
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||||
|
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters this instance as an autoloader.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function unregister()
|
||||||
|
{
|
||||||
|
spl_autoload_unregister(array($this, 'loadClass'));
|
||||||
|
|
||||||
|
if (null !== $this->vendorDir) {
|
||||||
|
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the given class or interface.
|
||||||
|
*
|
||||||
|
* @param string $class The name of the class
|
||||||
|
* @return true|null True if loaded, null otherwise
|
||||||
|
*/
|
||||||
|
public function loadClass($class)
|
||||||
|
{
|
||||||
|
if ($file = $this->findFile($class)) {
|
||||||
|
$includeFile = self::$includeFile;
|
||||||
|
$includeFile($file);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the path to the file where the class is defined.
|
||||||
|
*
|
||||||
|
* @param string $class The name of the class
|
||||||
|
*
|
||||||
|
* @return string|false The path if found, false otherwise
|
||||||
|
*/
|
||||||
|
public function findFile($class)
|
||||||
|
{
|
||||||
|
// class map lookup
|
||||||
|
if (isset($this->classMap[$class])) {
|
||||||
|
return $this->classMap[$class];
|
||||||
|
}
|
||||||
|
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (null !== $this->apcuPrefix) {
|
||||||
|
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||||
|
if ($hit) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $this->findFileWithExtension($class, '.php');
|
||||||
|
|
||||||
|
// Search for Hack files if we are running on HHVM
|
||||||
|
if (false === $file && defined('HHVM_VERSION')) {
|
||||||
|
$file = $this->findFileWithExtension($class, '.hh');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $this->apcuPrefix) {
|
||||||
|
apcu_add($this->apcuPrefix.$class, $file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $file) {
|
||||||
|
// Remember that this class does not exist.
|
||||||
|
$this->missingClasses[$class] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the currently registered loaders keyed by their corresponding vendor directories.
|
||||||
|
*
|
||||||
|
* @return array<string, self>
|
||||||
|
*/
|
||||||
|
public static function getRegisteredLoaders()
|
||||||
|
{
|
||||||
|
return self::$registeredLoaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $class
|
||||||
|
* @param string $ext
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
|
private function findFileWithExtension($class, $ext)
|
||||||
|
{
|
||||||
|
// PSR-4 lookup
|
||||||
|
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||||
|
|
||||||
|
$first = $class[0];
|
||||||
|
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||||
|
$subPath = $class;
|
||||||
|
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||||
|
$subPath = substr($subPath, 0, $lastPos);
|
||||||
|
$search = $subPath . '\\';
|
||||||
|
if (isset($this->prefixDirsPsr4[$search])) {
|
||||||
|
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||||
|
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||||
|
if (file_exists($file = $dir . $pathEnd)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-4 fallback dirs
|
||||||
|
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 lookup
|
||||||
|
if (false !== $pos = strrpos($class, '\\')) {
|
||||||
|
// namespaced class name
|
||||||
|
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||||
|
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||||
|
} else {
|
||||||
|
// PEAR-like class name
|
||||||
|
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->prefixesPsr0[$first])) {
|
||||||
|
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||||
|
if (0 === strpos($class, $prefix)) {
|
||||||
|
foreach ($dirs as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 fallback dirs
|
||||||
|
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 include paths.
|
||||||
|
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function initializeIncludeClosure()
|
||||||
|
{
|
||||||
|
if (self::$includeFile !== null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope isolated include.
|
||||||
|
*
|
||||||
|
* Prevents access to $this/self from included files.
|
||||||
|
*
|
||||||
|
* @param string $file
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
self::$includeFile = \Closure::bind(static function($file) {
|
||||||
|
include $file;
|
||||||
|
}, null, null);
|
||||||
|
}
|
||||||
|
}
|
359
vendor/composer/InstalledVersions.php
vendored
Normal file
359
vendor/composer/InstalledVersions.php
vendored
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer;
|
||||||
|
|
||||||
|
use Composer\Autoload\ClassLoader;
|
||||||
|
use Composer\Semver\VersionParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is copied in every Composer installed project and available to all
|
||||||
|
*
|
||||||
|
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||||
|
*
|
||||||
|
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||||
|
*
|
||||||
|
* @final
|
||||||
|
*/
|
||||||
|
class InstalledVersions
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var mixed[]|null
|
||||||
|
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||||
|
*/
|
||||||
|
private static $installed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool|null
|
||||||
|
*/
|
||||||
|
private static $canGetVendors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
private static $installedByVendor = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
* @psalm-return list<string>
|
||||||
|
*/
|
||||||
|
public static function getInstalledPackages()
|
||||||
|
{
|
||||||
|
$packages = array();
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
$packages[] = array_keys($installed['versions']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 === \count($packages)) {
|
||||||
|
return $packages[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all package names with a specific type e.g. 'library'
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
* @return string[]
|
||||||
|
* @psalm-return list<string>
|
||||||
|
*/
|
||||||
|
public static function getInstalledPackagesByType($type)
|
||||||
|
{
|
||||||
|
$packagesByType = array();
|
||||||
|
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
foreach ($installed['versions'] as $name => $package) {
|
||||||
|
if (isset($package['type']) && $package['type'] === $type) {
|
||||||
|
$packagesByType[] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $packagesByType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given package is installed
|
||||||
|
*
|
||||||
|
* This also returns true if the package name is provided or replaced by another package
|
||||||
|
*
|
||||||
|
* @param string $packageName
|
||||||
|
* @param bool $includeDevRequirements
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (isset($installed['versions'][$packageName])) {
|
||||||
|
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given package satisfies a version constraint
|
||||||
|
*
|
||||||
|
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||||
|
*
|
||||||
|
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||||
|
*
|
||||||
|
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||||
|
* @param string $packageName
|
||||||
|
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||||
|
{
|
||||||
|
$constraint = $parser->parseConstraints((string) $constraint);
|
||||||
|
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||||
|
|
||||||
|
return $provided->matches($constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||||
|
*
|
||||||
|
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||||
|
* whether a given version of a package is installed, and not just whether it exists
|
||||||
|
*
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string Version constraint usable with composer/semver
|
||||||
|
*/
|
||||||
|
public static function getVersionRanges($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ranges = array();
|
||||||
|
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
|
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(' || ', $ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||||
|
*/
|
||||||
|
public static function getVersion($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||||
|
*/
|
||||||
|
public static function getPrettyVersion($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||||
|
*/
|
||||||
|
public static function getReference($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['reference'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||||
|
*/
|
||||||
|
public static function getInstallPath($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||||
|
*/
|
||||||
|
public static function getRootPackage()
|
||||||
|
{
|
||||||
|
$installed = self::getInstalled();
|
||||||
|
|
||||||
|
return $installed[0]['root'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the raw installed.php data for custom implementations
|
||||||
|
*
|
||||||
|
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
||||||
|
*/
|
||||||
|
public static function getRawData()
|
||||||
|
{
|
||||||
|
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||||
|
|
||||||
|
if (null === self::$installed) {
|
||||||
|
// only require the installed.php file if this file is loaded from its dumped location,
|
||||||
|
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||||
|
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||||
|
self::$installed = include __DIR__ . '/installed.php';
|
||||||
|
} else {
|
||||||
|
self::$installed = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$installed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||||
|
*
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
public static function getAllRawData()
|
||||||
|
{
|
||||||
|
return self::getInstalled();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lets you reload the static array from another file
|
||||||
|
*
|
||||||
|
* This is only useful for complex integrations in which a project needs to use
|
||||||
|
* this class but then also needs to execute another project's autoloader in process,
|
||||||
|
* and wants to ensure both projects have access to their version of installed.php.
|
||||||
|
*
|
||||||
|
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||||
|
* the data it needs from this class, then call reload() with
|
||||||
|
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||||
|
* the project in which it runs can then also use this class safely, without
|
||||||
|
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||||
|
*
|
||||||
|
* @param array[] $data A vendor/composer/installed.php data set
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||||
|
*/
|
||||||
|
public static function reload($data)
|
||||||
|
{
|
||||||
|
self::$installed = $data;
|
||||||
|
self::$installedByVendor = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
private static function getInstalled()
|
||||||
|
{
|
||||||
|
if (null === self::$canGetVendors) {
|
||||||
|
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||||
|
}
|
||||||
|
|
||||||
|
$installed = array();
|
||||||
|
|
||||||
|
if (self::$canGetVendors) {
|
||||||
|
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||||
|
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||||
|
$installed[] = self::$installedByVendor[$vendorDir];
|
||||||
|
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||||
|
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||||
|
$required = require $vendorDir.'/composer/installed.php';
|
||||||
|
$installed[] = self::$installedByVendor[$vendorDir] = $required;
|
||||||
|
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||||
|
self::$installed = $installed[count($installed) - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === self::$installed) {
|
||||||
|
// only require the installed.php file if this file is loaded from its dumped location,
|
||||||
|
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||||
|
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||||
|
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||||
|
$required = require __DIR__ . '/installed.php';
|
||||||
|
self::$installed = $required;
|
||||||
|
} else {
|
||||||
|
self::$installed = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::$installed !== array()) {
|
||||||
|
$installed[] = self::$installed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed;
|
||||||
|
}
|
||||||
|
}
|
21
vendor/composer/LICENSE
vendored
Normal file
21
vendor/composer/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
10
vendor/composer/autoload_classmap.php
vendored
Normal file
10
vendor/composer/autoload_classmap.php
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_classmap.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||||
|
);
|
9
vendor/composer/autoload_namespaces.php
vendored
Normal file
9
vendor/composer/autoload_namespaces.php
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_namespaces.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
);
|
13
vendor/composer/autoload_psr4.php
vendored
Normal file
13
vendor/composer/autoload_psr4.php
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_psr4.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Modules\\Usermanagement\\Tests\\' => array($baseDir . '/tests'),
|
||||||
|
'Modules\\Usermanagement\\Database\\Seeders\\' => array($baseDir . '/database/seeders'),
|
||||||
|
'Modules\\Usermanagement\\Database\\Factories\\' => array($baseDir . '/database/factories'),
|
||||||
|
'Modules\\Usermanagement\\' => array($baseDir . '/app'),
|
||||||
|
);
|
36
vendor/composer/autoload_real.php
vendored
Normal file
36
vendor/composer/autoload_real.php
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_real.php @generated by Composer
|
||||||
|
|
||||||
|
class ComposerAutoloaderInit2864198e9d1b1265f9eb249b3c2e2689
|
||||||
|
{
|
||||||
|
private static $loader;
|
||||||
|
|
||||||
|
public static function loadClassLoader($class)
|
||||||
|
{
|
||||||
|
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||||
|
require __DIR__ . '/ClassLoader.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Composer\Autoload\ClassLoader
|
||||||
|
*/
|
||||||
|
public static function getLoader()
|
||||||
|
{
|
||||||
|
if (null !== self::$loader) {
|
||||||
|
return self::$loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_autoload_register(array('ComposerAutoloaderInit2864198e9d1b1265f9eb249b3c2e2689', 'loadClassLoader'), true, true);
|
||||||
|
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||||
|
spl_autoload_unregister(array('ComposerAutoloaderInit2864198e9d1b1265f9eb249b3c2e2689', 'loadClassLoader'));
|
||||||
|
|
||||||
|
require __DIR__ . '/autoload_static.php';
|
||||||
|
call_user_func(\Composer\Autoload\ComposerStaticInit2864198e9d1b1265f9eb249b3c2e2689::getInitializer($loader));
|
||||||
|
|
||||||
|
$loader->register(true);
|
||||||
|
|
||||||
|
return $loader;
|
||||||
|
}
|
||||||
|
}
|
51
vendor/composer/autoload_static.php
vendored
Normal file
51
vendor/composer/autoload_static.php
vendored
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_static.php @generated by Composer
|
||||||
|
|
||||||
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
|
class ComposerStaticInit2864198e9d1b1265f9eb249b3c2e2689
|
||||||
|
{
|
||||||
|
public static $prefixLengthsPsr4 = array (
|
||||||
|
'M' =>
|
||||||
|
array (
|
||||||
|
'Modules\\Usermanagement\\Tests\\' => 29,
|
||||||
|
'Modules\\Usermanagement\\Database\\Seeders\\' => 40,
|
||||||
|
'Modules\\Usermanagement\\Database\\Factories\\' => 42,
|
||||||
|
'Modules\\Usermanagement\\' => 23,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $prefixDirsPsr4 = array (
|
||||||
|
'Modules\\Usermanagement\\Tests\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/../..' . '/tests',
|
||||||
|
),
|
||||||
|
'Modules\\Usermanagement\\Database\\Seeders\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/../..' . '/database/seeders',
|
||||||
|
),
|
||||||
|
'Modules\\Usermanagement\\Database\\Factories\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/../..' . '/database/factories',
|
||||||
|
),
|
||||||
|
'Modules\\Usermanagement\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/../..' . '/app',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $classMap = array (
|
||||||
|
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||||
|
);
|
||||||
|
|
||||||
|
public static function getInitializer(ClassLoader $loader)
|
||||||
|
{
|
||||||
|
return \Closure::bind(function () use ($loader) {
|
||||||
|
$loader->prefixLengthsPsr4 = ComposerStaticInit2864198e9d1b1265f9eb249b3c2e2689::$prefixLengthsPsr4;
|
||||||
|
$loader->prefixDirsPsr4 = ComposerStaticInit2864198e9d1b1265f9eb249b3c2e2689::$prefixDirsPsr4;
|
||||||
|
$loader->classMap = ComposerStaticInit2864198e9d1b1265f9eb249b3c2e2689::$classMap;
|
||||||
|
|
||||||
|
}, null, ClassLoader::class);
|
||||||
|
}
|
||||||
|
}
|
5
vendor/composer/installed.json
vendored
Normal file
5
vendor/composer/installed.json
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"packages": [],
|
||||||
|
"dev": true,
|
||||||
|
"dev-package-names": []
|
||||||
|
}
|
23
vendor/composer/installed.php
vendored
Normal file
23
vendor/composer/installed.php
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php return array(
|
||||||
|
'root' => array(
|
||||||
|
'name' => 'putrakuningan/usermanagement',
|
||||||
|
'pretty_version' => '1.0.0+no-version-set',
|
||||||
|
'version' => '1.0.0.0',
|
||||||
|
'reference' => null,
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../../',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev' => true,
|
||||||
|
),
|
||||||
|
'versions' => array(
|
||||||
|
'putrakuningan/usermanagement' => array(
|
||||||
|
'pretty_version' => '1.0.0+no-version-set',
|
||||||
|
'version' => '1.0.0.0',
|
||||||
|
'reference' => null,
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../../',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
4
vite.config.js
Normal file
4
vite.config.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export const paths = [
|
||||||
|
'Modules/Usermanagement/resources/assets/sass/app.scss',
|
||||||
|
'Modules/Usermanagement/resources/assets/js/app.js',
|
||||||
|
];
|
Loading…
Reference in New Issue
Block a user