first commit
Some checks failed
Build / run (push) Has been cancelled

This commit is contained in:
maher
2025-10-29 11:42:25 +01:00
commit 703f50a09d
4595 changed files with 385164 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
<?php namespace Common\Pages;
use App\Models\User;
use Common\Core\BaseController;
use Common\Notifications\ContactPageMessage;
use Common\Settings\Settings;
use Illuminate\Http\Request;
class ContactPageController extends BaseController
{
public function sendMessage(Request $request)
{
if ( ! config('common.site.enable_contact_page')) return abort(404);
$this->validate($request, [
'name' => 'required|string|min:5',
'email' => 'required|email',
'message' => 'required|string|min:10'
]);
$notification = new ContactPageMessage($request->all());
(new User())->forceFill([
'name' => config('mail.from.name'),
'email' => app(Settings::class)->get('mail.contact_page_address', config('mail.from.address')),
])->notify($notification);
}
}

23
common/Pages/CrupdatePage.php Executable file
View File

@@ -0,0 +1,23 @@
<?php
namespace Common\Pages;
use Common\Workspaces\ActiveWorkspace;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
class CrupdatePage
{
public function execute(CustomPage $page, array $data): CustomPage
{
if (!$page->exists) {
$data['user_id'] = Auth::id();
$data['slug'] = $data['slug'] ?? slugify(Arr::get($data, 'title'));
$data['workspace_id'] = app(ActiveWorkspace::class)->id ?? 0;
}
$page->fill($data)->save();
return $page;
}
}

93
common/Pages/CustomPage.php Executable file
View File

@@ -0,0 +1,93 @@
<?php namespace Common\Pages;
use App\Models\User;
use Common\Core\BaseModel;
use Common\Tags\Tag;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Support\Str;
class CustomPage extends BaseModel
{
use HasFactory;
const PAGE_TYPE = 'default';
const MODEL_TYPE = 'customPage';
protected $guarded = ['id'];
protected $casts = [
'id' => 'integer',
'hide_nav' => 'boolean',
'meta' => 'json',
];
protected $appends = ['model_type'];
protected function slug(): Attribute
{
return Attribute::make(
set: fn (string $value) => slugify($value),
);
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function tags(): MorphToMany
{
return $this->morphToMany(Tag::class, 'taggable');
}
public function toSearchableArray(): array
{
return [
'id' => $this->id,
'title' => $this->title,
'body' => $this->body,
'slug' => $this->slug,
'type' => $this->type,
'created_at' => $this->created_at->timestamp ?? '_null',
'updated_at' => $this->updated_at->timestamp ?? '_null',
'user_id' => $this->user_id,
'workspace_id' => $this->workspace_id ?? '_null',
];
}
public function toNormalizedArray(): array
{
return [
'id' => $this->id,
'name' => $this->title,
'image' => $this->meta['image'] ?? null,
'description' => Str::limit($this->body, 100),
'model_type' => static::MODEL_TYPE,
];
}
public static function filterableFields(): array
{
return [
'id',
'user_id',
'created_at',
'updated_at',
'type',
'workspace_id',
];
}
public static function getModelTypeAttribute(): string
{
return static::MODEL_TYPE;
}
public static function factory(): CustomPageFactory
{
return CustomPageFactory::new();
}
}

View File

@@ -0,0 +1,143 @@
<?php namespace Common\Pages;
use Auth;
use Common\Core\BaseController;
use Common\Database\Datasource\Datasource;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Str;
class CustomPageController extends BaseController
{
/**
* CustomPage model might get overwritten with
* parent page model, for example, LinkPage
*/
public function __construct(
protected CustomPage $page,
protected Request $request,
) {
}
public function index()
{
$userId = $this->request->get('userId');
$this->authorize('index', [get_class($this->page), $userId]);
$builder = $this->page->newQuery();
// make sure we filter by page type on full text engines for
// example, only search "link page" on "meilisearch" on "belink"
$modelType = $this->page::PAGE_TYPE;
$pageType = $this->request->get(
'type',
$modelType !== 'default' ? $modelType : null,
);
if ($pageType) {
$builder->where('type', '=', $pageType);
}
if ($userId) {
$builder->where('user_id', '=', $userId);
}
$pagination = (new Datasource($builder, $this->request->all()))
->paginate()
->toArray();
$pagination['data'] = array_map(function ($page) {
$page['body'] = Str::limit(strip_tags($page['body']), 100);
return $page;
}, $pagination['data']);
return $this->success(['pagination' => $pagination]);
}
public function show(int|string $id)
{
$page = $this->page
->where('slug', $id)
->orWhere('id', $id)
->firstOrFail();
$this->authorize('show', $page);
return $this->renderClientOrApi([
'pageName' => 'custom-page',
'data' => [
'page' => $page,
'loader' => 'customPage',
],
]);
}
public function store()
{
$this->authorize('store', get_class($this->page));
$validatedData = $this->validate($this->request, [
'title' => [
'string',
'min:3',
'max:250',
Rule::unique('custom_pages')->where('user_id', Auth::id()),
],
'slug' => [
'nullable',
'string',
'min:3',
'max:250',
Rule::unique('custom_pages'),
],
'body' => 'required|string|min:1',
'meta' => 'nullable|array',
]);
$page = app(CrupdatePage::class)->execute(
$this->page->newInstance(),
$validatedData,
);
return $this->success(['page' => $page]);
}
public function update(int $id)
{
$page = $this->page->findOrFail($id);
$this->authorize('update', $page);
$validatedData = $this->validate($this->request, [
'title' => [
'string',
'min:3',
'max:250',
Rule::unique('custom_pages')
->where('user_id', $page->user_id)
->ignore($page->id),
],
'slug' => [
'nullable',
'string',
'min:3',
'max:250',
Rule::unique('custom_pages')->ignore($page->id),
],
'body' => 'string|min:1',
'meta' => 'nullable|array',
]);
$page = app(CrupdatePage::class)->execute($page, $validatedData);
return $this->success(['page' => $page]);
}
public function destroy(string $ids)
{
$pageIds = explode(',', $ids);
$this->authorize('destroy', [get_class($this->page), $pageIds]);
$this->page->whereIn('id', $pageIds)->delete();
return $this->success();
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Common\Pages;
use Carbon\CarbonPeriod;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Arr;
class CustomPageFactory extends Factory
{
protected $model = CustomPage::class;
public function definition(): array
{
$period = CarbonPeriod::create(now()->subMonths(3), now());
return [
'body' => $this->faker->randomHtml(),
'slug' => $this->faker->slug(3),
'title' => $this->faker->words(3, true),
'workspace_id' => 0,
'user_id' => 1,
'created_at' => Arr::random($period->toArray()),
'updated_at' => Arr::random($period->toArray()),
];
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Common\Pages;
use Illuminate\Support\Collection;
class LoadCustomPageMenuItems
{
public function execute(): Collection
{
return app(CustomPage::class)
->limit(40)
->where('type', 'default')
->get()
->map(function (CustomPage $page) {
return [
'id' => $page->id,
'label' => $page->title ?: $page->slug,
'action' => "/pages/{$page->slug}",
'model_id' => $page->id,
'type' => 'customPage',
];
});
}
}