mTopicId = NULL; parent::__construct(); if ($iTopicId || $iTopicName) { $this->loadTopic( [ 'topic_id' => $iTopicId, 'topic_name' => $iTopicName ]); } } public function isValid() { return ($this->verifyId($this->mTopicId)); } public function loadTopic($iParamHash = NULL) { $whereSQL = ' WHERE artt.'; $ret = NULL; if (@$this->verifyId($iParamHash['topic_id']) || !empty($iParamHash['topic_name'])) { $whereSQL .= "`".((@$this->verifyId($iParamHash['topic_id']) || $this->mTopicId) ? 'topic_id' : 'topic_name')."` = ?"; $bindVars = [ ( @$this->verifyId( $iParamHash['topic_id'] ) ? (int) $iParamHash['topic_id'] : ( $this->mTopicId ?: $iParamHash['topic_name'] ) ) ]; $sql = "SELECT artt.*". "FROM `".BIT_DB_PREFIX."article_topics` artt ". $whereSQL; $this->mInfo = $this->mDb->getRow($sql, $bindVars); if( !empty( $this->mInfo['topic_id'] ) ) { $this->mTopicId = $this->mInfo['topic_id']; $this->mInfo['topic_image_url'] = ( $this->mInfo['has_topic_image'] ) ? $this->getTopicImageStorageUrl( null, false, true ) : null; } } return $ret; } public function verify(&$iParamHash) { // Validate the (optional) topic_id parameter $cleanHash['topic_id'] = ( @$this->verifyId( $iParamHash['topic_id'] ) ) ? (int) $iParamHash['topic_id'] : null; // Was an acceptable name given? if (empty($iParamHash['topic_name']) || ($iParamHash['topic_name'] == '')) { $this->mErrors['topic_name'] = KernelTools::tra("Invalid or blank topic name supplied"); } elseif (empty($iParamHash['topic_id'])) { $ret = $this->getTopicList( [ 'topic_name' => $iParamHash['topic_name'] ] ); if ( sizeof( $ret ) ) { $this->mErrors['topic_name'] = 'Topic "'.$iParamHash['topic_name'].'" already exists. Please choose a different name.'; } else { $cleanHash['topic_name'] = $iParamHash['topic_name']; } } else { $cleanHash['topic_name'] = $iParamHash['topic_name']; } // Whether the topic is active or not if ( empty($iParamHash['active_topic']) || (strtoupper($iParamHash['active_topic']) != 'CHECKED' && strtoupper($iParamHash['active_topic']) != 'ON' && strtoupper($iParamHash['active_topic']) != 'Y')) { $cleanHash['active_topic'] = ( @$this->verifyId( $cleanHash['topic_id'] ) ) ? 'n' : 'y'; } else { $cleanHash['active_topic'] = 'y'; } if (empty($iParamHash['created'])) { global $gBitSystem; $cleanHash['created'] = $gBitSystem->getUTCTime(); } $iParamHash = $cleanHash; return(count($this->mErrors) == 0); } public function storeTopic($iParamHash = NULL) { global $gLibertySystem; global $gBitUser; if ($this->verify($iParamHash)) { $topicId = ( !$iParamHash['topic_id'] ) ? $this->mDb->GenID( 'article_topics_id_seq' ) : $this->mTopicId; if( !empty( $_FILES['upload'] ) && $_FILES['upload']['tmp_name'] ) { $checkFunc = \Bitweaver\Liberty\liberty_get_function( 'can_thumbnail' ); if( $checkFunc( $_FILES['upload']['type'] )) { $fileHash = $_FILES['upload']; $fileHash['dest_branch'] = $this->getTopicImageBaseUrl( $topicId ); $fileHash['source_file'] = $fileHash['tmp_name']; \Bitweaver\Liberty\liberty_clear_thumbnails( $fileHash ); \Bitweaver\Liberty\liberty_generate_thumbnails( $fileHash ); $iParamHash['has_topic_image'] = 'y'; } else { $this->mErrors = KernelTools::tra( "The file you uploaded doesn't appear to be a valid image. The reported mime type is" ).": ".$_FILES['upload']['type']; } } if( $iParamHash['topic_id'] ) { $this->mDb->associateUpdate( BIT_DB_PREFIX."article_topics", $iParamHash, [ 'topic_id' => $iParamHash['topic_id'] ] ); } else { $iParamHash['topic_id'] = $topicId; $this->mDb->associateInsert( BIT_DB_PREFIX."article_topics", $iParamHash ); } } $this->mTopicId = $iParamHash['topic_id']; } /** * Work out the path to the image for this article * @param $pTopicId id of the article we need the image path for * @param $pBasePathOnly bool TRUE / FALSE - specify whether you want full path or just base path * @return string on success, FALSE on failure * @access public **/ public function getTopicImageBaseUrl($pTopicId = NULL) { $ret = FALSE; if ( !@BitBase::verifyId( $pTopicId ) && $this->isValid() ) { $pTopicId = $this->mTopicId; } if( @BitBase::verifyId( $pTopicId )) { $ret = \Bitweaver\Liberty\liberty_mime_get_storage_branch( 'topics/'.$pTopicId ); } return $ret; } /** * Get the full URL to the needed thumbnail * * @param numeric $pTopicId Topic ID of topic in question * @access public * @return string Path to thumbnail, FALSE on failure */ public function getTopicImageThumbUrl($pTopicId = NULL) { global $gBitSystem; $ret = FALSE; if ( !@BitBase::verifyId( $pTopicId ) && $this->isValid() ) { $pTopicId = $this->mTopicId; } if ( @BitBase::verifyId( $pTopicId )) { $ret = \Bitweaver\Liberty\liberty_fetch_thumbnail_url( [ 'source_file' => BitArticleTopic::getTopicImageBaseUrl( $pTopicId ), 'default_image' => $gBitSystem->getConfig( 'articles_image_size', 'small' ), ]); } return $ret; } public static function getTopicList($pOptionHash=NULL) { global $gBitSystem; $where = ''; $bindVars = []; if ( !empty( $pOptionHash['active_topic'] ) ) { $where = " WHERE artt.`active_topic` = 'y' "; } if ( !empty( $pOptionHash['topic_name'] ) ) { $where = " WHERE artt.`topic_name` = ? "; $bindVars[] = $pOptionHash['topic_name']; } $query = "SELECT artt.* FROM `".BIT_DB_PREFIX."article_topics` artt $where ORDER BY artt.`topic_name`"; $result = $gBitSystem->mDb->query( $query, $bindVars ); $ret = []; while ( $res = $result->fetchRow() ) { $res["num_articles"] = $gBitSystem->mDb->getOne( "SELECT COUNT(*) FROM `".BIT_DB_PREFIX."articles` WHERE `topic_id`= ?", [ $res["topic_id"] ] ); if ( empty( $res['topic_image_url'] ) && $res['has_topic_image'] == 'y' ) { $res['topic_image_url'] = BitArticleTopic::getTopicImageStorageUrl( $res['topic_id'] ); } $ret[] = $res; } return $ret; } public function removeTopicImage() { if ($this->mTopicId) { if ( file_exists($this->getTopicImageStoragePath() ) ) { @unlink( $this->getTopicImageStoragePath() ); } $sql = "UPDATE `".BIT_DB_PREFIX."article_topics` SET `has_topic_image` = 'n' WHERE `topic_id` = ?"; $rs = $this->mDb->query($sql, [$this->mTopicId]); $this->mInfo['has_topic_image'] = 'n'; } } public function activateTopic() { $this->setActivation(TRUE); } public function deactivateTopic() { $this->setActivation(FALSE); } public function setActivation($iIsActive = FALSE) { $sql = "UPDATE `".BIT_DB_PREFIX."article_topics` SET `active_topic` = '".($iIsActive ? 'y' : 'n')."' WHERE `topic_id` = ?"; $rs = $this->mDb->query($sql, [$this->mTopicId]); $this->mInfo['active_topic'] = ($iIsActive ? 'y' : 'n'); } public function getTopicArticles() { if (!$this->mTopicId) { return []; } $sql = "SELECT `article_id` FROM `".BIT_DB_PREFIX."articles` WHERE `topic_id` = ?"; $rs = $this->mDb->query($sql, [ $this->mTopicId ]); $ret = []; while ($row = $rs->fetchRow()) { $tmpArticle = new BitArticle($row['article_id']); $tmpArticle->load(); $ret[] = $tmpArticle; } } public function removeTopic($iRemoveArticles = FALSE) { if (!$this->mTopicId) { return NULL; } $this->removeTopicImage(); if ($iRemoveArticles == TRUE) { $topicArticles = $this->getTopicArticles(); for ($articleCount = 0; $articleCount < count($topicArticles); $articleCount++) { $topicArticles[$articleCount]->expunge(); } } else { $sql = "UPDATE `".BIT_DB_PREFIX."articles` SET `topic_id` = ? WHERE `topic_id` = ?"; $rs = $this->mDb->query($sql, [ null, $this->mTopicId ]); } $sql = "DELETE FROM `".BIT_DB_PREFIX."article_topics` WHERE `topic_id` = ?"; $rs = $this->mDb->query($sql, [ $this->mTopicId ]); } /***************************************************************************** * Image functions needed for backward compatability - these are needed to * * handle old article image style images that are not attachments. generally * * these functions are deprecated but needed for legacy code * ****************************************************************************/ /** * Get the name of the article image file * * @param array $pTopicId article id * @access public * @return string on success */ public function getTopicImageStorageName($pTopicId = NULL) { if ( !@BitBase::verifyId( $pTopicId ) ) { if ( $this->isValid() ) { $pTopicId = $this->mTopicId; } else { return ''; } } global $gBitSystem; return "topic_$pTopicId.".$gBitSystem->getConfig( 'liberty_thumbnail_format', 'jpg' ); } /** * Work out the path to the image for this article * @param $pTopicId id of the article we need the image path for * @param $pBasePathOnly bool TRUE / FALSE - specify whether you want full path or just base path * @return string path on success, FALSE on failure * @access public **/ public function getTopicImageStoragePath($pTopicId = NULL, $pBasePathOnly = FALSE) { $path = BitArticleTopic::getArticleImageStoragePath( NULL, TRUE ); if ($pBasePathOnly) { return $path; } if ( !@BitBase::verifyId( $pTopicId ) ) { if( $this->isValid() ) { $pTopicId = $this->mTopicId; } else { return ''; } } if ( !empty( $pTopicId ) ) { return $path.BitArticleTopic::getTopicImageStorageName( $pTopicId ); } return ''; } /** * Work out the URL to the image for this article * @param $pTopicId id of the article we need the image path for * @param $pBasePathOnly bool TRUE / FALSE - specify whether you want full path or just base path * @return string URL on success, FALSE on failure * @access public **/ public function getTopicImageStorageUrl($pTopicId = NULL, $pBasePathOnly = FALSE, $pForceRefresh = FALSE) { global $gBitSystem; $ret = false; // first we check to see if this is a new type thumbnail. if that fails we'll use the old method if ( !( $ret = BitArticleTopic::getTopicImageThumbUrl( $pTopicId ))) { $url = BitArticleTopic::getArticleImageStorageUrl( NULL, TRUE ); if ($pBasePathOnly) { return $url; } if ( !@BitBase::verifyId( $pTopicId ) ) { if ( $this->isValid() ) { $pTopicId = $this->mTopicId; } else { return false; } } if ( is_file( BitArticleTopic::getTopicImageStoragePath( NULL, TRUE ).BitArticleTopic::getTopicImageStorageName( $pTopicId ))) { $ret = $url.BitArticleTopic::getTopicImageStorageName( $pTopicId ).( $pForceRefresh ? "?".$gBitSystem->getUTCTime() : '' ); } } return str_replace( "//", "/", $ret ); } /***************************************************************************** * Image functions needed for backward compatability - these are needed to * * handle old article image style images that are not attachments. generally * * these functions are deprecated but needed for legacy code * * * * the legacy code below here should go at some point. this code is old and * * fugly. In fact, a lot of the code in here is fugly. we should use * * pigoenholes to do this topic thing, now that pigoenholes can have primary * * attachments. * ****************************************************************************/ /** * Get the name of the article image file * * @param array $pArticleId article id * @access public * @return string on success, FALSE on failure */ public function getArticleImageStorageName($pArticleId = NULL) { if ( !@BitBase::verifyId( $pArticleId ) ) { if ( $this->isValid() ) { $pArticleId = $this->mArticleId; } else { return NULL; } } return "article_$pArticleId.jpg"; } /** * Work out the path to the image for this article * @param $pArticleId id of the article we need the image path for * @param $pBasePathOnly bool TRUE / FALSE - specify whether you want full path or just base path * @return string path on success, FALSE on failure * @access public **/ public function getArticleImageStoragePath($pArticleId = NULL, $pBasePathOnly = FALSE) { $path = STORAGE_PKG_PATH.ARTICLES_PKG_NAME.'/'; if ( !is_dir( $path ) ) { KernelTools::mkdir_p( $path ); } if ($pBasePathOnly) { return $path; } if( !@BitBase::verifyId( $pArticleId ) ) { if( $this->isValid() ) { $pArticleId = $this->mArticleId; } else { return NULL; } } if ( !empty( $pArticleId ) ) { return $path.BitArticleTopic::getArticleImageStorageName( $pArticleId ); } return FALSE; } /** * Work out the URL to the image for this article * @param $pArticleId id of the article we need the image path for * @param $pBasePathOnly bool TRUE / FALSE - specify whether you want full path or just base path * @return string URL on success, FALSE on failure * @access public **/ public function getArticleImageStorageUrl($pArticleId = NULL, $pBasePathOnly = FALSE, $pForceRefresh = FALSE) { global $gBitSystem; $url = STORAGE_PKG_URL.ARTICLES_PKG_NAME.'/'; if ($pBasePathOnly) { return $url; } if( !@BitBase::verifyId( $pArticleId ) ) { if( $this->isValid() ) { $pArticleId = $this->mArticleId; } else { return NULL; } } if ( is_file( BitArticleTopic::getArticleImageStoragePath( NULL, TRUE ).BitArticleTopic::getArticleImageStorageName( $pArticleId ) ) ) { return $url.BitArticleTopic::getArticleImageStorageName( $pArticleId ).( $pForceRefresh ? "?".$gBitSystem->getUTCTime() : '' ); } return FALSE; } }