2023-07-15 17:02:46 +00:00
< ? php
namespace Misuzu\News ;
use InvalidArgumentException ;
use RuntimeException ;
use Index\DateTime ;
2023-07-22 14:00:51 +00:00
use Index\Data\DbStatementCache ;
2023-07-15 17:02:46 +00:00
use Index\Data\IDbConnection ;
use Index\Data\IDbResult ;
use Misuzu\Pagination ;
2023-07-15 23:58:17 +00:00
use Misuzu\Comments\CommentsCategoryInfo ;
2023-08-02 22:12:47 +00:00
use Misuzu\Users\UserInfo ;
2023-07-15 17:02:46 +00:00
class News {
private IDbConnection $dbConn ;
private DbStatementCache $cache ;
public function __construct ( IDbConnection $dbConn ) {
$this -> dbConn = $dbConn ;
$this -> cache = new DbStatementCache ( $dbConn );
}
2023-08-05 13:50:15 +00:00
public function countCategories (
? bool $hidden = null
) : int {
$hasHidden = $hidden !== null ;
2023-07-15 17:02:46 +00:00
$query = 'SELECT COUNT(*) FROM msz_news_categories' ;
2023-08-05 13:50:15 +00:00
if ( $hasHidden )
$query .= sprintf ( ' WHERE category_is_hidden %s 0' , $hidden ? '<>' : '=' );
2023-07-15 17:02:46 +00:00
$result = $this -> dbConn -> query ( $query );
$count = 0 ;
if ( $result -> next ())
$count = $result -> getInteger ( 0 );
return $count ;
}
2023-08-05 13:50:15 +00:00
public function getCategories (
? bool $hidden = null ,
2023-07-15 17:02:46 +00:00
? Pagination $pagination = null
) : array {
2023-08-05 13:50:15 +00:00
$hasHidden = $hidden !== null ;
2023-07-15 17:02:46 +00:00
$hasPagination = $pagination !== null ;
$query = 'SELECT category_id, category_name, category_description, category_is_hidden, UNIX_TIMESTAMP(category_created), (SELECT COUNT(*) FROM msz_news_posts AS np WHERE np.category_id = nc.category_id) AS category_posts_count FROM msz_news_categories AS nc' ;
2023-08-05 13:50:15 +00:00
if ( $hasHidden )
$query .= sprintf ( ' WHERE category_is_hidden %s 0' , $hidden ? '<>' : '=' );
2023-07-15 17:02:46 +00:00
$query .= ' ORDER BY category_created ASC' ;
if ( $hasPagination )
$query .= ' LIMIT ? OFFSET ?' ;
$stmt = $this -> cache -> get ( $query );
$args = 0 ;
if ( $hasPagination ) {
$stmt -> addParameter ( ++ $args , $pagination -> getRange ());
$stmt -> addParameter ( ++ $args , $pagination -> getOffset ());
}
$stmt -> execute ();
2023-08-05 13:50:15 +00:00
$result = $stmt -> getResult ();
$categories = [];
2023-07-15 17:02:46 +00:00
2023-08-05 13:50:15 +00:00
while ( $result -> next ())
$categories [] = new NewsCategoryInfo ( $result );
2023-07-15 17:02:46 +00:00
2023-08-05 13:50:15 +00:00
return $categories ;
}
2023-07-15 17:02:46 +00:00
2023-08-05 13:50:15 +00:00
public function getCategory (
? string $categoryId = null ,
NewsPostInfo | string | null $postInfo = null
) : NewsCategoryInfo {
$hasCategoryId = $categoryId !== null ;
$hasPostInfo = $postInfo !== null ;
2023-07-15 17:02:46 +00:00
2023-08-05 13:50:15 +00:00
if ( ! $hasCategoryId && ! $hasPostInfo )
throw new InvalidArgumentException ( 'At least one argument must be specified.' );
if ( $hasCategoryId && $hasPostInfo )
throw new InvalidArgumentException ( 'Only one argument may be specified.' );
2023-07-15 17:02:46 +00:00
2023-08-05 13:50:15 +00:00
$value = null ;
$query = 'SELECT category_id, category_name, category_description, category_is_hidden, UNIX_TIMESTAMP(category_created) FROM msz_news_categories' ;
if ( $hasCategoryId ) {
$query .= ' WHERE category_id = ?' ;
$value = $categoryId ;
}
if ( $hasPostInfo ) {
if ( $postInfo instanceof NewsPostInfo ) {
$query .= ' WHERE category_id = ?' ;
$value = $postInfo -> getCategoryId ();
} else {
$query .= ' WHERE category_id = (SELECT category_id FROM msz_news_posts WHERE post_id = ?)' ;
$value = $postInfo ;
}
}
2023-07-15 17:02:46 +00:00
2023-08-05 13:50:15 +00:00
$stmt = $this -> cache -> get ( $query );
$stmt -> addParameter ( 1 , $value );
2023-07-15 17:02:46 +00:00
$stmt -> execute ();
$result = $stmt -> getResult ();
if ( ! $result -> next ())
2023-08-05 13:50:15 +00:00
throw new RuntimeException ( 'News category not found.' );
2023-07-15 17:02:46 +00:00
return new NewsCategoryInfo ( $result );
}
public function createCategory (
string $name ,
string $description ,
bool $hidden
) : NewsCategoryInfo {
$name = trim ( $name );
if ( empty ( $name ))
throw new InvalidArgumentException ( '$name may not be empty' );
$description = trim ( $description );
if ( empty ( $description ))
throw new InvalidArgumentException ( '$description may not be empty' );
$stmt = $this -> cache -> get ( 'INSERT INTO msz_news_categories (category_name, category_description, category_is_hidden) VALUES (?, ?, ?)' );
$stmt -> addParameter ( 1 , $name );
$stmt -> addParameter ( 2 , $description );
$stmt -> addParameter ( 3 , $hidden ? 1 : 0 );
$stmt -> execute ();
2023-08-05 13:50:15 +00:00
return $this -> getCategory ( categoryId : ( string ) $this -> dbConn -> getLastInsertId ());
2023-07-15 17:02:46 +00:00
}
public function deleteCategory ( NewsCategoryInfo | string $infoOrId ) : void {
if ( $infoOrId instanceof NewsCategoryInfo )
$infoOrId = $infoOrId -> getId ();
$stmt = $this -> cache -> get ( 'DELETE FROM msz_news_categories WHERE category_id = ?' );
$stmt -> addParameter ( 1 , $infoOrId );
$stmt -> execute ();
}
public function updateCategory (
NewsCategoryInfo | string $infoOrId ,
? string $name = null ,
? string $description = null ,
? bool $hidden = null
) : void {
if ( $infoOrId instanceof NewsCategoryInfo )
$infoOrId = $infoOrId -> getId ();
if ( $name !== null ) {
$name = trim ( $name );
if ( empty ( $name ))
throw new InvalidArgumentException ( '$name may not be empty' );
}
if ( $description !== null ) {
$description = trim ( $description );
if ( empty ( $description ))
throw new InvalidArgumentException ( '$description may not be empty' );
}
$hasHidden = $hidden !== null ;
$stmt = $this -> cache -> get ( 'UPDATE msz_news_categories SET category_name = COALESCE(?, category_name), category_description = COALESCE(?, category_description), category_is_hidden = IF(?, ?, category_is_hidden) WHERE category_id = ?' );
$stmt -> addParameter ( 1 , $name );
$stmt -> addParameter ( 2 , $description );
$stmt -> addParameter ( 3 , $hasHidden ? 1 : 0 );
$stmt -> addParameter ( 4 , $hidden ? 1 : 0 );
$stmt -> addParameter ( 5 , $infoOrId );
$stmt -> execute ();
}
2023-08-05 13:50:15 +00:00
public function countPosts (
NewsCategoryInfo | string | null $categoryInfo = null ,
2023-07-15 17:02:46 +00:00
bool $onlyFeatured = false ,
bool $includeScheduled = false ,
bool $includeDeleted = false
) : int {
2023-08-05 13:50:15 +00:00
if ( $categoryInfo instanceof NewsCategoryInfo )
$categoryInfo = $categoryInfo -> getId ();
$hasCategoryInfo = $categoryInfo !== null ;
2023-07-15 17:02:46 +00:00
$args = 0 ;
$query = 'SELECT COUNT(*) FROM msz_news_posts' ;
2023-08-05 13:50:15 +00:00
if ( $hasCategoryInfo ) {
2023-07-18 22:24:23 +00:00
++ $args ;
2023-08-05 13:50:15 +00:00
$query .= ' WHERE category_id = ?' ;
}
if ( $onlyFeatured ) {
$query .= ( ++ $args > 1 ? ' AND' : ' WHERE' );
$query .= ' post_is_featured = 1' ;
2023-07-15 17:02:46 +00:00
}
if ( ! $includeScheduled ) {
$query .= ( ++ $args > 1 ? ' AND' : ' WHERE' );
$query .= ' post_scheduled <= NOW()' ;
}
if ( ! $includeDeleted ) {
$query .= ( ++ $args > 1 ? ' AND' : ' WHERE' );
$query .= ' post_deleted IS NULL' ;
}
$stmt = $this -> cache -> get ( $query );
2023-08-05 13:50:15 +00:00
if ( $hasCategoryInfo )
$stmt -> addParameter ( 1 , $categoryInfo );
2023-07-15 17:02:46 +00:00
$stmt -> execute ();
$result = $stmt -> getResult ();
$count = 0 ;
if ( $result -> next ())
$count = $result -> getInteger ( 0 );
return $count ;
}
2023-08-05 13:50:15 +00:00
public function getPosts (
NewsCategoryInfo | string | null $categoryInfo = null ,
string $searchQuery = null ,
2023-07-15 17:02:46 +00:00
bool $onlyFeatured = false ,
bool $includeScheduled = false ,
bool $includeDeleted = false ,
? Pagination $pagination = null
) : array {
2023-08-05 13:50:15 +00:00
if ( $categoryInfo instanceof NewsCategoryInfo )
$categoryInfo = $categoryInfo -> getId ();
$hasCategoryInfo = $categoryInfo !== null ;
$hasSearchQuery = $searchQuery !== null ;
2023-07-15 17:02:46 +00:00
$hasPagination = $pagination !== null ;
2023-08-05 13:50:15 +00:00
$args = 0 ;
$query = 'SELECT post_id, category_id, user_id, comment_section_id, post_is_featured, post_title, post_text, UNIX_TIMESTAMP(post_scheduled), UNIX_TIMESTAMP(post_created), UNIX_TIMESTAMP(post_updated), UNIX_TIMESTAMP(post_deleted) FROM msz_news_posts' ;
if ( $hasCategoryInfo ) {
2023-07-18 22:24:23 +00:00
++ $args ;
2023-08-05 13:50:15 +00:00
$query .= ' WHERE category_id = ?' ;
}
if ( $hasSearchQuery ) {
$query .= ( ++ $args > 1 ? ' AND' : ' WHERE' );
$query .= ' MATCH(post_title, post_text) AGAINST (? IN NATURAL LANGUAGE MODE)' ;
}
if ( $onlyFeatured ) {
$query .= ( ++ $args > 1 ? ' AND' : ' WHERE' );
$query .= ' post_is_featured = 1' ;
2023-07-15 17:02:46 +00:00
}
if ( ! $includeScheduled ) {
$query .= ( ++ $args > 1 ? ' AND' : ' WHERE' );
$query .= ' post_scheduled <= NOW()' ;
}
if ( ! $includeDeleted ) {
$query .= ( ++ $args > 1 ? ' AND' : ' WHERE' );
$query .= ' post_deleted IS NULL' ;
}
2023-08-05 13:50:15 +00:00
$query .= ' ORDER BY post_scheduled DESC' ;
2023-07-15 17:02:46 +00:00
if ( $hasPagination )
$query .= ' LIMIT ? OFFSET ?' ;
$stmt = $this -> cache -> get ( $query );
$args = 0 ;
2023-08-05 13:50:15 +00:00
if ( $hasCategoryInfo )
$stmt -> addParameter ( ++ $args , $categoryInfo );
if ( $hasSearchQuery )
$stmt -> addParameter ( ++ $args , $searchQuery );
2023-07-15 17:02:46 +00:00
if ( $hasPagination ) {
$stmt -> addParameter ( ++ $args , $pagination -> getRange ());
$stmt -> addParameter ( ++ $args , $pagination -> getOffset ());
}
$stmt -> execute ();
2023-08-05 13:50:15 +00:00
$result = $stmt -> getResult ();
$posts = [];
2023-07-15 17:02:46 +00:00
2023-08-05 13:50:15 +00:00
while ( $result -> next ())
$posts [] = new NewsPostInfo ( $result );
2023-07-15 17:02:46 +00:00
2023-08-05 13:50:15 +00:00
return $posts ;
2023-07-15 17:02:46 +00:00
}
2023-08-05 13:50:15 +00:00
public function getPost ( string $postId ) : NewsPostInfo {
2023-07-15 17:02:46 +00:00
$stmt = $this -> cache -> get ( 'SELECT post_id, category_id, user_id, comment_section_id, post_is_featured, post_title, post_text, UNIX_TIMESTAMP(post_scheduled), UNIX_TIMESTAMP(post_created), UNIX_TIMESTAMP(post_updated), UNIX_TIMESTAMP(post_deleted) FROM msz_news_posts WHERE post_id = ?' );
$stmt -> addParameter ( 1 , $postId );
$stmt -> execute ();
$result = $stmt -> getResult ();
if ( ! $result -> next ())
throw new RuntimeException ( 'No news post with that ID exists.' );
return new NewsPostInfo ( $result );
}
public function createPost (
NewsCategoryInfo | string $categoryInfo ,
string $title ,
string $body ,
bool $featured = false ,
2023-08-02 22:12:47 +00:00
UserInfo | string | null $userInfo = null ,
2023-07-15 17:02:46 +00:00
DateTime | int | null $schedule = null
) : NewsPostInfo {
if ( $categoryInfo instanceof NewsCategoryInfo )
$categoryInfo = $categoryInfo -> getId ();
2023-08-02 22:12:47 +00:00
if ( $userInfo instanceof UserInfo )
$userInfo = $userInfo -> getId ();
2023-07-15 17:02:46 +00:00
if ( $schedule instanceof DateTime )
$schedule = $schedule -> getUnixTimeSeconds ();
$title = trim ( $title );
if ( empty ( $title ))
throw new InvalidArgumentException ( '$title may not be empty' );
$body = trim ( $body );
if ( empty ( $body ))
throw new InvalidArgumentException ( '$body may not be empty' );
$stmt = $this -> cache -> get ( 'INSERT INTO msz_news_posts (category_id, user_id, post_is_featured, post_title, post_text, post_scheduled) VALUES (?, ?, ?, ?, ?, ?)' );
$stmt -> addParameter ( 1 , $categoryInfo );
$stmt -> addParameter ( 2 , $userInfo );
$stmt -> addParameter ( 3 , $featured ? 1 : 0 );
$stmt -> addParameter ( 4 , $title );
$stmt -> addParameter ( 5 , $body );
$stmt -> addParameter ( 6 , $schedule );
$stmt -> execute ();
2023-08-05 13:50:15 +00:00
return $this -> getPost (( string ) $this -> dbConn -> getLastInsertId ());
2023-07-15 17:02:46 +00:00
}
public function deletePost ( NewsPostInfo | string $postInfo ) : void {
if ( $postInfo instanceof NewsPostInfo )
$postInfo = $postInfo -> getId ();
$stmt = $this -> cache -> get ( 'UPDATE msz_news_posts SET post_deleted = COALESCE(post_deleted, NOW()) WHERE post_id = ?' );
$stmt -> addParameter ( 1 , $postInfo );
$stmt -> execute ();
}
public function restorePost ( NewsPostInfo | string $postInfo ) : void {
if ( $postInfo instanceof NewsPostInfo )
$postInfo = $postInfo -> getId ();
$stmt = $this -> cache -> get ( 'UPDATE msz_news_posts SET post_deleted = NULL WHERE post_id = ?' );
$stmt -> addParameter ( 1 , $postInfo );
$stmt -> execute ();
}
public function nukePost ( NewsPostInfo | string $postInfo ) : void {
if ( $postInfo instanceof NewsPostInfo )
$postInfo = $postInfo -> getId ();
// should this enforce a soft delete first? (AND post_deleted IS NOT NULL)
$stmt = $this -> cache -> get ( 'DELETE FROM msz_news_posts WHERE post_id = ?' );
$stmt -> addParameter ( 1 , $postInfo );
$stmt -> execute ();
}
public function updatePost (
NewsPostInfo | string $postInfo ,
NewsCategoryInfo | string | null $categoryInfo = null ,
? string $title = null ,
? string $body = null ,
? bool $featured = null ,
bool $updateUserInfo = false ,
2023-08-02 22:12:47 +00:00
UserInfo | string | null $userInfo = null ,
2023-07-15 17:02:46 +00:00
DateTime | int | null $schedule = null
) : void {
if ( $postInfo instanceof NewsPostInfo )
$postInfo = $postInfo -> getId ();
if ( $categoryInfo instanceof NewsCategoryInfo )
$categoryInfo = $categoryInfo -> getId ();
2023-08-02 22:12:47 +00:00
if ( $userInfo instanceof UserInfo )
$userInfo = $userInfo -> getId ();
2023-07-15 17:02:46 +00:00
if ( $schedule instanceof DateTime )
$schedule = $schedule -> getUnixTimeSeconds ();
if ( $title !== null ) {
$title = trim ( $title );
if ( empty ( $title ))
throw new InvalidArgumentException ( '$title may not be empty' );
}
if ( $body !== null ) {
$body = trim ( $body );
if ( empty ( $body ))
throw new InvalidArgumentException ( '$body may not be empty' );
}
$hasFeatured = $featured !== null ;
$stmt = $this -> cache -> get ( 'UPDATE msz_news_posts SET category_id = COALESCE(?, category_id), user_id = IF(?, ?, user_id), post_is_featured = IF(?, ?, post_is_featured), post_title = COALESCE(?, post_title), post_text = COALESCE(?, post_text), post_scheduled = COALESCE(?, post_scheduled) WHERE post_id = ?' );
$stmt -> addParameter ( 1 , $categoryInfo );
$stmt -> addParameter ( 2 , $updateUserInfo ? 1 : 0 );
$stmt -> addParameter ( 3 , $userInfo );
$stmt -> addParameter ( 4 , $hasFeatured ? 1 : 0 );
$stmt -> addParameter ( 5 , $featured ? 1 : 0 );
$stmt -> addParameter ( 6 , $title );
$stmt -> addParameter ( 7 , $body );
$stmt -> addParameter ( 8 , $schedule );
$stmt -> addParameter ( 9 , $postInfo );
$stmt -> execute ();
}
public function updatePostCommentCategory (
NewsPostInfo | string $postInfo ,
2023-07-15 23:58:17 +00:00
CommentsCategoryInfo | string $commentsCategory
2023-07-15 17:02:46 +00:00
) : void {
if ( $postInfo instanceof NewsPostInfo )
$postInfo = $postInfo -> getId ();
2023-07-15 23:58:17 +00:00
if ( $commentsCategory instanceof CommentsCategoryInfo )
$commentsCategory = $commentsCategory -> getId ();
2023-07-15 17:02:46 +00:00
2023-07-15 23:58:17 +00:00
$stmt = $this -> cache -> get ( 'UPDATE msz_news_posts SET comment_section_id = ? WHERE post_id = ?' );
$stmt -> addParameter ( 1 , $commentsCategory );
$stmt -> addParameter ( 2 , $postInfo );
2023-07-15 17:02:46 +00:00
$stmt -> execute ();
}
}