126 lines
3.6 KiB
PHP
126 lines
3.6 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Models;
|
||
|
|
|
||
|
|
use CodeIgniter\Model;
|
||
|
|
|
||
|
|
class NewsModel extends Model
|
||
|
|
{
|
||
|
|
protected $table = 'news';
|
||
|
|
protected $primaryKey = 'id';
|
||
|
|
protected $useAutoIncrement = true;
|
||
|
|
protected $returnType = 'array';
|
||
|
|
protected $useSoftDeletes = false;
|
||
|
|
protected $protectFields = true;
|
||
|
|
protected $allowedFields = ['title', 'slug', 'content', 'content_json', 'content_html', 'excerpt', 'status', 'published_at', 'created_by'];
|
||
|
|
|
||
|
|
protected bool $allowEmptyInserts = false;
|
||
|
|
|
||
|
|
protected $useTimestamps = true;
|
||
|
|
protected $dateFormat = 'datetime';
|
||
|
|
protected $createdField = 'created_at';
|
||
|
|
protected $updatedField = 'updated_at';
|
||
|
|
protected $deletedField = null;
|
||
|
|
|
||
|
|
// Validation
|
||
|
|
protected $validationRules = [
|
||
|
|
'title' => 'required|min_length[3]|max_length[255]',
|
||
|
|
'slug' => 'required|max_length[255]|is_unique[news.slug,id,{id}]',
|
||
|
|
'content' => 'required',
|
||
|
|
'status' => 'required|in_list[draft,published]',
|
||
|
|
];
|
||
|
|
|
||
|
|
protected $validationMessages = [
|
||
|
|
'title' => [
|
||
|
|
'required' => 'Judul berita harus diisi.',
|
||
|
|
'min_length' => 'Judul berita minimal 3 karakter.',
|
||
|
|
'max_length' => 'Judul berita maksimal 255 karakter.',
|
||
|
|
],
|
||
|
|
'slug' => [
|
||
|
|
'required' => 'Slug harus diisi.',
|
||
|
|
'is_unique' => 'Slug sudah digunakan, silakan gunakan judul yang berbeda.',
|
||
|
|
],
|
||
|
|
'content' => [
|
||
|
|
'required' => 'Konten berita harus diisi.',
|
||
|
|
],
|
||
|
|
'status' => [
|
||
|
|
'required' => 'Status harus dipilih.',
|
||
|
|
'in_list' => 'Status harus draft atau published.',
|
||
|
|
],
|
||
|
|
];
|
||
|
|
|
||
|
|
protected $skipValidation = false;
|
||
|
|
protected $cleanValidationRules = true;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Generate slug from title
|
||
|
|
*/
|
||
|
|
public function generateSlug(string $title, ?int $excludeId = null): string
|
||
|
|
{
|
||
|
|
// Convert to lowercase and replace spaces with hyphens
|
||
|
|
$slug = strtolower(trim($title));
|
||
|
|
$slug = preg_replace('/[^a-z0-9-]/', '-', $slug);
|
||
|
|
$slug = preg_replace('/-+/', '-', $slug);
|
||
|
|
$slug = trim($slug, '-');
|
||
|
|
|
||
|
|
// If slug is empty, use timestamp
|
||
|
|
if (empty($slug)) {
|
||
|
|
$slug = 'news-' . time();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check if slug exists
|
||
|
|
$baseSlug = $slug;
|
||
|
|
$counter = 1;
|
||
|
|
while ($this->slugExists($slug, $excludeId)) {
|
||
|
|
$slug = $baseSlug . '-' . $counter;
|
||
|
|
$counter++;
|
||
|
|
}
|
||
|
|
|
||
|
|
return $slug;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if slug exists
|
||
|
|
*/
|
||
|
|
protected function slugExists(string $slug, ?int $excludeId = null): bool
|
||
|
|
{
|
||
|
|
$builder = $this->where('slug', $slug);
|
||
|
|
|
||
|
|
if ($excludeId !== null) {
|
||
|
|
$builder->where('id !=', $excludeId);
|
||
|
|
}
|
||
|
|
|
||
|
|
return $builder->countAllResults() > 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get news with creator information
|
||
|
|
*/
|
||
|
|
public function getNewsWithCreator(int $limit = 10, int $offset = 0, ?string $status = null)
|
||
|
|
{
|
||
|
|
$builder = $this->select('news.*, users.username as creator_name')
|
||
|
|
->join('users', 'users.id = news.created_by', 'left');
|
||
|
|
|
||
|
|
if ($status !== null) {
|
||
|
|
$builder->where('news.status', $status);
|
||
|
|
}
|
||
|
|
|
||
|
|
return $builder->orderBy('news.created_at', 'DESC')
|
||
|
|
->limit($limit, $offset)
|
||
|
|
->findAll();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Count news by status
|
||
|
|
*/
|
||
|
|
public function countByStatus(?string $status = null): int
|
||
|
|
{
|
||
|
|
if ($status !== null) {
|
||
|
|
return $this->where('status', $status)->countAllResults();
|
||
|
|
}
|
||
|
|
|
||
|
|
return $this->countAllResults();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|