NewsNewsFeaturesDownloadsDevelopmentSupportForumDocumentsAbout Us

articles.class.php

查看本檔案說明文件.
00001 <?php
00002 
00003     include_once( PLOG_CLASS_PATH.'class/dao/model.class.php' );
00004     include_once( PLOG_CLASS_PATH.'class/dao/article.class.php' );
00005     include_once( PLOG_CLASS_PATH.'class/dao/articlecategories.class.php' );
00006     include_once( PLOG_CLASS_PATH.'class/dao/articlenotifications.class.php' );
00007     include_once( PLOG_CLASS_PATH.'class/dao/articlecomments.class.php' );
00008     include_once( PLOG_CLASS_PATH.'class/dao/articlecommentstatus.class.php' ); 
00009     include_once( PLOG_CLASS_PATH.'class/dao/users.class.php' );
00010     include_once( PLOG_CLASS_PATH.'class/dao/trackbacks.class.php' );
00011     include_once( PLOG_CLASS_PATH.'class/data/timestamp.class.php' );
00012     include_once( PLOG_CLASS_PATH.'class/config/config.class.php' );
00013     include_once( PLOG_CLASS_PATH.'class/dao/blogs.class.php' );
00014     include_once( PLOG_CLASS_PATH.'class/data/textfilter.class.php' );
00015     include_once( PLOG_CLASS_PATH.'class/dao/customfields/customfieldsvalues.class.php' );
00016     include_once( PLOG_CLASS_PATH.'class/dao/customfields/customfields.class.php' );
00017 
00018     include_once( PLOG_CLASS_PATH.'class/logger/LogUtil.php' );
00019 
00025     class Articles extends Model
00026     {
00027 
00028         // DAO objects that we keep for later, so that we don't have
00029         // to create them eeeeevery time!
00030         var $categories;
00031         var $comments;
00032         var $trackbacks;
00033         var $users;
00034         var $blogs;
00035         var $customfields;      
00036         var $_blogInfo;
00037         var $_blogSettings;
00038         var $_timeDiff;
00039 
00040         function Articles()
00041         {
00042             $this->Model();
00043             $this->categories = new ArticleCategories();
00044             $this->comments = new ArticleComments();
00045             $this->trackbacks = new Trackbacks();
00046             $this->users      = new Users();
00047             $this->blogs      = new Blogs();
00048             $this->customfields = new CustomFieldsValues();         
00049             // fine, this is not very nice but it helps a lot, specially if all the classes
00050             // that need to load articles share the same instance       
00051             $this->cache      = Array();    
00052             $this->_blogInfo  = null;
00053             $this->_timeDiff  = 0;
00054             $this->_blogsettings = null;
00055         }
00056 
00065         function getUserArticle( $artId, $userId = -1 )
00066         {
00067             $query = "SELECT * FROM ".$this->getPrefix()."articles WHERE id = '".Db::qstr($artId)."'";
00068             if( $userId != -1 )
00069                 $query .= " AND user_id = '".Db::qstr($userId)."'";
00070             $query .= ";";
00071 
00072             // we send the query and then fetch the first array with the result
00073             $result = $this->Execute( $query );
00074 
00075             if ( $result->RecordCount() == 0)
00076                 return false;
00077 
00078             $row = $result->FetchRow( $result );
00079 
00080             $article = $this->_fillArticleInformation( $row );
00081             
00082             $result->Close();            
00083 
00084             return $article;
00085         }
00086 
00094         function getBlogArticle( $artId, $blogId = -1, $includeHiddenFields = true, $date = -1, $categoryId = -1, $userId = -1, $status = POST_STATUS_ALL, $maxDate = -1 )
00095         {
00096             $prefix = $this->getPrefix();
00097             $query = "SELECT a.id, a.date,
00098                              a.user_id,a.blog_id,a.status,a.properties,
00099                              a.num_reads, a.slug FROM {$prefix}articles a ";
00100             // thanks jon for the tip :) You're right that the amount of rows will be too big if we don't really need these
00101             // fields!
00102             if($categoryId != -1 && $blogId != -1) {
00103                 $query .= ", {$prefix}articles_categories c, {$prefix}article_categories_link l ";
00104             }
00105             
00106             $query .= "WHERE a.id = ".Db::qstr($artId);
00107                      
00108             if( $blogId != -1 )
00109                 $query .= " AND a.blog_id = ".Db::qstr($blogId);
00110             if( $date != -1 && $maxDate == -1 ) {
00111                 $query .= " AND a.date+0 LIKE '$date%'";
00112             } elseif ( $date != -1 && $maxDate != -1 ) {
00113                 $query .= " AND a.date+0 >= $date AND a.date+0 <= $maxDate";
00114             }
00115             if( $userId != -1 ) 
00116                 $query .= " AND a.user_id = ".Db::qstr($userId);
00117             if( $categoryId != -1 )
00118                 $query .= " AND c.id = ".Db::qstr($categoryId)." AND c.id = l.category_id AND a.id = l.article_id";
00119             if( $status != POST_STATUS_ALL )
00120                 $query .= " AND a.status = $status;";
00121                 
00122             return $this->_getBlogArticleFromQuery( $query, $includeHiddenFields );
00123         }
00124         
00133         function getBlogArticleByTitle( $artTitle, $blogId = -1, $includeHiddenFields = true, $date = -1, $categoryId = -1, $userId = -1, $status = POST_STATUS_PUBLISHED, $maxDate = -1 )
00134         {
00135             $prefix = $this->getPrefix();
00136             $query = "SELECT a.id, a.date,
00137                              a.user_id,a.blog_id,a.status,a.properties,
00138                              a.num_reads, a.slug FROM {$prefix}articles a ";
00139             // thanks jon once again :)
00140             if($categoryId != -1 && $blogId != -1) {
00141                 $query .= ",{$prefix}articles_categories c, {$prefix}article_categories_link l ";
00142             }
00143             $query .= "WHERE a.slug = '".Db::qstr($artTitle)."'";
00144             if( $blogId != -1 )
00145                 $query .= " AND a.blog_id = ".Db::qstr($blogId);
00146             if( $date != -1 && $maxDate == -1 ) {
00147                 $query .= " AND a.date+0 LIKE '$date%'";
00148             } elseif ( $date != -1 && $maxDate != -1 ) {
00149                 $query .= " AND a.date+0 >= $date AND a.date+0 <= $maxDate";
00150             }
00151             if( $userId != -1 ) 
00152                 $query .= " AND a.user_id = ".Db::qstr($userId);
00153             if( $categoryId != -1 ) {
00154                 $query .= " AND c.id = ".Db::qstr($categoryId)." AND c.id = l.category_id AND a.id = l.article_id";
00155             }
00156                 
00157             $query .= " AND a.status = $status;";
00158             
00159             return $this->_getBlogArticleFromQuery( $query, $includeHiddenFields );
00160         }
00161         
00165         function _getBlogArticleFromQuery( $query, $includeHiddenFields )
00166         {
00167             // we send the query and then fetch the first array with the result
00168             $result = $this->Execute( $query );
00169 
00170             if( $result == false )
00171                 return false;
00172 
00173             if ( $result->RecordCount() == 0)
00174                 return false;
00175 
00176             $row = $result->FetchRow( $result );
00177 
00178             $article = $this->_fillArticleInformation( $row, $includeHiddenFields );
00179             
00180             $result->Close();            
00181 
00182             return $article;        
00183         }
00184 
00191         function getBlogNextArticle( $article )
00192         {
00193             // we need to keep the timestamp in mind
00194             $date = $article->getDateObject();
00195             $articleCorrectedDate = Timestamp::getDateWithOffset( $article->getDate(), -($article->getTimeOffset()));
00196             $blogId = $article->getBlog();
00197 
00198             // gets the article that is just next in time
00199             $query = "SELECT * FROM ".$this->getPrefix()."articles 
00200                               WHERE date > '".$articleCorrectedDate."' AND status = '".Db::qstr(POST_STATUS_PUBLISHED)."' 
00201                                     AND blog_id = '".Db::qstr($blogId)."' ORDER BY date ASC LIMIT 1;";
00202             
00203             return( $this->_getBlogArticleFromQuery( $query, false ));
00204         }
00205 
00212         function getBlogPrevArticle( $article )
00213         {
00214             // we need to keep the timestamp in mind
00215             $date = $article->getDateObject();
00216             $articleCorrectedDate = Timestamp::getDateWithOffset( $article->getDate(), -($article->getTimeOffset()));
00217             $blogId = $article->getBlog();          
00218         
00219             // gets the article that is just previous in time
00220             $query = "SELECT * FROM ".$this->getPrefix()."articles 
00221                                WHERE date < '".$articleCorrectedDate."' AND status = ".POST_STATUS_PUBLISHED." 
00222                                      AND blog_id = '".Db::qstr($blogId)."' ORDER BY date DESC LIMIT 1;";
00223                                      
00224             return( $this->_getBlogArticleFromQuery( $query, false ));
00225         }
00226         
00235         function searchBlogArticles( $blogId, $searchTerms )
00236         {
00237             $posts = $this->getBlogArticles( $blogId,
00238                                              -1, // no date
00239                                              -1, // no amount
00240                                              0, // no category id
00241                                              0, // not any status
00242                                              0, // not belonging to any user id in particular
00243                                              0, // no maximum date
00244                                              $searchTerms // the only thing we're taking into account: the search terms!!
00245                                              );
00246                                                  
00247             return $posts;
00248         }
00249         
00255         function buildWhere( $blogid, $date = -1, $amount = -1, $categoryId = 0, $status = 0, $userId = 0, $maxDate = 0, $searchTerms = "" )
00256         {
00257             $postStatus = $status;
00258             $prefix = $this->getPrefix();
00259             if($blogid == -1){
00260                 $query = "a.blog_id = a.blog_id";
00261             }
00262             else{
00263                 $query = "a.blog_id = ".Db::qstr($blogid);
00264             }
00265             if( $date != -1 ) {
00266                 // consider the time difference
00267                 $blogSettings = $this->blogs->getBlogSettings( $blogid );
00268                 $timeDifference = $blogSettings->getValue( "time_offset" );
00269                 $SecondsDiff = $timeDifference * 3600;
00270                 $query .= " AND FROM_UNIXTIME(UNIX_TIMESTAMP(a.date)+$SecondsDiff)+0 LIKE '$date%'";
00271             }
00272 
00273             // the common part "c.id = a.category_id" is needed so that
00274             // we don't get one article row as many times as the amount of categories
00275             // we have... due to the sql 'join' operation we're carrying out
00276             if( $categoryId == -1 )
00277                 $query .= " AND c.id = l.category_id AND a.id = l.article_id ";
00278             else {
00279                 if( $categoryId > 0 )
00280                     $query .= " AND a.id = l.article_id AND l.category_id = $categoryId AND c.id = l.category_id";
00281                 else {
00282                     $query .= " AND c.id = l.category_id AND a.id = l.article_id AND c.in_main_page = 1";
00283                 }
00284             }
00285 
00286             if( $status > 0 )
00287                 $query .= " AND a.status = '$postStatus'";
00288             if( $userId > 0 )
00289                 $query .= " AND a.user_id = ".Db::qstr($userId);
00290             if( $maxDate > 0 )
00291                 $query .= " AND a.date <= '$maxDate'";
00292                 
00293             // in case there were some search terms specified as parameters...
00294             if( $searchTerms != "" ) {
00295                 // load the class dynamically so that we don't have to waste memory
00296                 // if we're not going to need it!
00297                 include_once( PLOG_CLASS_PATH."class/dao/searchengine.class.php" );         
00298                 $searchEngine = new SearchEngine();
00299                 
00300                 // prepare the query string
00301                 $searchTerms = $searchEngine->_adaptSearchString( $searchTerms );
00302                 $whereString = $searchEngine->_generateSearchArticlesWhereString( $searchTerms );
00303                 
00304                 // and add it to the current search
00305                 $query .=" AND {$whereString} ";    
00306             }
00307                 
00308             if( $categoryId <= 0 )
00309                 $query .= " GROUP BY a.id ";
00310 
00311                 
00312             return $query;
00313         }
00314         
00318         function getNumBlogArticles( $blogid, $date = -1, $amount = -1, $categoryId = -1, $status = 0, $userId = 0, $maxDate = 0, $searchTerms = "" )
00319         {       
00320             $postStatus = $status;
00321             $prefix = $this->getPrefix();           
00322             $where = $this->buildWhere( $blogid, $date, $amount, $categoryId, $status, $userId, $maxDate, $searchTerms );   
00323             $query = "SELECT COUNT(*) AS total FROM {$prefix}articles a, {$prefix}articles_categories c, 
00324                              {$prefix}article_categories_link l";
00325             if( $searchTerms != "" )
00326                 $query .= ", {$prefix}articles_text t ";
00327                 
00328             if( $searchTerms != "" )
00329                 $query .= "WHERE t.article_id = a.id AND $where";
00330             else
00331                 $query .= " WHERE $where";          
00332                 
00333             if( $categoryId != -1 )
00334                 $query .= " GROUP BY a.id";
00335                                                               
00336             $result = $this->_db->Execute( $query );
00337             
00338             if( !$result )
00339                 return 0;
00340                                 
00341             $number = $result->RowCount();
00342             
00343             $result->Close();
00344             
00345             return( $number );            
00346         }
00347 
00364         function getBlogArticles( $blogid, $date = -1, $amount = -1, $categoryId = 0, $status = 0, $userId = 0, 
00365                                   $maxDate = 0, $searchTerms = "", $page = -1 )
00366         {
00367             // build the query
00368             // the query gets quite complicated to build because we have to take care of plenty
00369             // of conditions, such as the maximum date, the amount, the category,
00370             // wether the category has to be shown in the main page or not, etc...
00371             $postStatus = $status;
00372             $prefix = $this->getPrefix();
00373             $where = $this->buildWhere( $blogid, $date, $amount, $categoryId, $status, $userId, $maxDate, $searchTerms );
00374             $query = "SELECT a.id as id, a.id, a.date,
00375                              a.user_id,a.blog_id,a.status,a.properties,
00376                              a.num_reads, a.slug, 1 AS relevance FROM {$prefix}articles a, {$prefix}articles_categories c, 
00377                              {$prefix}article_categories_link l";
00378             if( $searchTerms != "" )
00379                 $query .= ", {$prefix}articles_text t ";
00380             $query .= " WHERE ";
00381             if( $searchTerms != "" )
00382                 $query .= " t.article_id = a.id AND ";
00383             $query .= " $where";
00384                       
00385     
00386             // if we're doing a search, we should sort by relevance
00387             if( $searchTerms != "" ) {
00388                 $query .= " ORDER BY relevance";            
00389             }
00390             else {
00391                 $query .= " ORDER BY a.date DESC";              
00392             }
00393             
00394             // we don't need limits if we're getting the posts for a given day
00395             if( ($amount > 0) && ($date == -1) && ($page == -1 ))
00396                 $query .= " LIMIT $amount;"; 
00397             
00398             // in case we're using a paged display
00399             if( $page > 0 ) {
00400                 $start = (($page - 1) * $amount);               
00401                 $query .= " LIMIT $start, $amount";   
00402             }
00403 
00404             // execute the query
00405             $result = $this->Execute( $query );
00406 
00407             if( !$result )
00408                 return Array();
00409                 
00410             if( $result->RowCount() == 0 )
00411                 return Array();
00412             
00413             $ids='';
00414 
00415             while( $row = $result->FetchRow()) {
00416                 $ids.='"'.$row["id"].'",';
00417                 $article = $this->_fillArticleHeaderInformation( $row );
00418                 $articles[] =$article;
00419             }
00420 
00421             $ids = substr($ids, 0, -1);          
00422             //$articleComments = $this->comments->getPostCommentsByIds( $ids, COMMENT_ORDER_NEWEST_FIRST, COMMENT_STATUS_ALL );
00423             //$articleTrackbacks = $this->trackbacks->getArticleTrackbacksByIds( $ids );
00424             $articleCategories = $this->categories->getArticleCategoriesByIds( $ids, $blogid );
00425             $articleTexts = $this->getArticlesText( $ids );
00426             
00427             foreach( $articles as $article ) {
00428                 $lastArticleId=$article->getId();
00429                 // These are functions normally called by _fillArticleInformation
00430                 // But now I moved to test getPostCommentsByIds
00431                 $categoryIds = Array();
00432                 
00433                 // fill in the article texts
00434                 $article->setText( $articleTexts[$lastArticleId]['text'] );
00435                 $article->setTopic( $articleTexts[$lastArticleId]['topic'] );
00436                 
00437                 foreach( $articleCategories[$lastArticleId] as $category )
00438                     $categoryIds[] = $category->getId();
00439                     
00440                 $article->setCategoryIds( $categoryIds );
00441                 $article->setCategories( $articleCategories[$lastArticleId] );
00442                 //$article->setNumTrackbacks(sizeof($articleTrackbacks[$lastArticleId]));
00443                 //$article->setTrackbacks($articleTrackbacks[$lastArticleId]);
00444                 //$article->setTotalComments(sizeof($articleComments[$lastArticleId]));
00445                 //$article->setComments($articleComments[$lastArticleId]);
00446                 //$article->setFields( $fields[$lastArticleId] );
00447 
00448                 $fullarticles[]=$article;
00449                 $this->cache[$lastArticleId] = $article;       
00450             }
00451             
00452             $result->Close();            
00453             
00454             return $fullarticles;
00455         }
00456 
00462         function getArticleIdFromName($articleName){
00463             $query = "SELECT id FROM ".$this->getPrefix()."articles ".
00464                      " WHERE slug = '".Db::qstr($articleName)."'";
00465 
00466             $result = $this->Execute($query);
00467 
00468             if($row = $result->FetchRow()){
00469               $result->Close();            
00470               if($row["id"])
00471                 return $row["id"];
00472             }
00473             return 0;
00474         }       
00475 
00476 
00477         
00485         function getArticlesText( $articleIds )
00486         {
00487             $prefix = $this->getPrefix();
00488             $query = "SELECT article_id,text,topic FROM {$prefix}articles_text WHERE
00489                       article_id IN (".$articleIds.")";
00490                       
00491             $result = $this->Execute( $query );
00492 
00493             // it's impossible that an article has no categories, but
00494             // we'll bear with it...
00495             if( !$result )
00496                 return Array();
00497 
00498             // otherwise, fetch them
00499             while ($row = $result->FetchRow()) {
00500                 $lastArticleId=$row["article_id"];
00501                 $postTexts[$lastArticleId]=$row;
00502             }
00503             
00504             $result->Close();           
00505             
00506             return( $postTexts );
00507         }
00508 
00516         function getBlogArticlesByQuery( $query )
00517         {
00518             $result = $this->Execute( $query );
00519             if( !$result ) return Array();
00520             $articles = Array();
00521             while( $row = $result->FetchRow()) {
00522                 $article = $this->_fillArticleInformation( $row );
00523                 $articles[] = $article;
00524             }
00525             
00526             $result->Close();            
00527             
00528             return $articles;
00529         }
00530 
00538         function getNumberPostsPerMonth( $blogId )
00539         {
00540             // query to get the earliest post
00541             // this must be my longest and most complex SQL query ever :)
00542             // $blogs = new Blogs();
00543             $blogSettings = $this->blogs->getBlogSettings( $blogId );
00544             if( $blogSettings->getValue( "show_future_posts_in_calendar" ))
00545                 $numPostsPerMonthQuery = "SELECT COUNT(*) AS 'count',YEAR(date) AS 'year',MONTH(date) AS 'month',DAYOFMONTH(date) AS 'daymonth' FROM ".$this->getPrefix()."articles WHERE status = 1 AND blog_id = ".$blogId." GROUP BY YEAR(date),MONTH(date) ORDER BY YEAR(date) DESC,MONTH(date) DESC;";
00546             else
00547                 $numPostsPerMonthQuery = "SELECT COUNT(*) AS 'count',YEAR(date) AS 'year',MONTH(date) AS 'month',DAYOFMONTH(date) AS 'daymonth' FROM ".$this->getPrefix()."articles WHERE status = 1 AND blog_id = ".$blogId." AND date <= NOW() GROUP BY YEAR(date),MONTH(date) ORDER BY YEAR(date) DESC,MONTH(date) DESC;";
00548 
00549             $result = $this->Execute( $numPostsPerMonthQuery);
00550             if( $result == false )
00551                 return false;
00552 
00553             $archives = Array();
00554             while( $row = $result->FetchRow()) {
00555                 $archives[$row["year"]][$row["month"]] = $row["count"];
00556             }
00557             
00558             $result->Close();            
00559 
00560             return $archives;
00561         }
00562         
00568         function getNumberPostsPerMonthAdmin( $blogId )
00569         {
00570             // query to get the earliest post
00571             // this must be my longest and most complex SQL query ever :)
00572             $numPostsPerMonthQuery = "SELECT COUNT(*) AS 'count', YEAR(date) AS 'year',
00573                                       MONTH(date) AS 'month', DAYOFMONTH(date) AS 'daymonth' 
00574                                       FROM ".$this->getPrefix()."articles 
00575                                       WHERE blog_id = $blogId 
00576                                       GROUP BY YEAR(date), MONTH(date) 
00577                                       ORDER BY YEAR(date) DESC,MONTH(date) DESC;";
00578 
00579             $result = $this->Execute( $numPostsPerMonthQuery);
00580             if( $result == false )
00581                 return false;
00582                 
00583             while( $row = $result->FetchRow()) {
00584                 $archives[$row["year"]][$row["month"]] = $row["count"];
00585             }
00586             
00587             $result->Close();            
00588 
00589             return $archives;
00590         }
00591 
00601         function getNumberPostsPerDay( $blogId, $year = null , $month = null )
00602         {
00603             // if month and/or year are empty, get the current ones
00604             if( $year == null ) {
00605                 $t = new Timestamp();
00606                 $year = $t->getYear();
00607             }
00608             if( $month == null ) {
00609                 $t = new Timestamp();
00610                 $month = $t->getMonth();
00611             }
00612 
00613             // another long sql query :) the id and date fields are there just in case we need to debug
00614             // but they're not included in the resulting array
00615             // $blogs = new Blogs();
00616             $blogSettings = $this->blogs->getBlogSettings( $blogId );
00617             // consider the time difference
00618             $timeDifference = $blogSettings->getValue( "time_offset" );
00619             $SecondsDiff = $timeDifference * 3600;
00620             // check whether we're supposed to show posts that happen in the future or not
00621             if( $blogSettings->getValue( "show_future_posts_in_calendar" ))
00622                 $numPostsPerDayQuery = "SELECT COUNT(*) AS 'count', DAYOFMONTH(FROM_UNIXTIME(UNIX_TIMESTAMP(date) + $SecondsDiff)) AS 'day', id AS 'id', date AS 'date' FROM ".$this->getPrefix()."articles WHERE status = 1 AND blog_id = ".$blogId." AND MONTH(FROM_UNIXTIME(UNIX_TIMESTAMP(date) + $SecondsDiff)) = ".$month." AND YEAR(FROM_UNIXTIME(UNIX_TIMESTAMP(date) + $SecondsDiff)) = ".$year." GROUP BY DAYOFMONTH(FROM_UNIXTIME(UNIX_TIMESTAMP(date) + $SecondsDiff));";
00623             else
00624                 $numPostsPerDayQuery = "SELECT COUNT(*) AS 'count', DAYOFMONTH(FROM_UNIXTIME(UNIX_TIMESTAMP(date) + $SecondsDiff)) AS 'day', id AS 'id', date AS 'date' FROM ".$this->getPrefix()."articles WHERE status = 1 AND blog_id = ".$blogId." AND date <= NOW() AND MONTH(FROM_UNIXTIME(UNIX_TIMESTAMP(date) + $SecondsDiff)) = ".$month." AND YEAR(FROM_UNIXTIME(UNIX_TIMESTAMP(date) + $SecondsDiff)) = ".$year." GROUP BY DAYOFMONTH(FROM_UNIXTIME(UNIX_TIMESTAMP(date) + $SecondsDiff));";
00625 
00626             $result = $this->Execute( $numPostsPerDayQuery );
00627 
00628             if( $result == false )
00629                 return 0;
00630 
00631             $postsPerDay = Array();
00632             while( $row = $result->FetchRow()) {
00633                 $postsPerDay[$row["day"]] = $row["count"];
00634             }
00635             
00636             $result->Close();            
00637 
00638             return $postsPerDay;
00639         }
00640 
00649         function addPostCategoriesLink( $articleId, $categories )
00650         {
00651             // nothing to do if the $categories array is not ehem, an array :)
00652             if( !is_array( $categories ))
00653                 return true;
00654                 
00655             foreach( $categories as $categoryId ) {
00656                 $query = "INSERT INTO ".$this->getPrefix()."article_categories_link
00657                           (article_id, category_id) VALUES ($articleId, $categoryId )";
00658                 $this->Execute( $query );
00659             }
00660 
00661             return true;
00662         }
00663 
00668         function deletePostCategoriesLink( $articleId )
00669         {
00670             $query = "DELETE FROM ".$this->getPrefix()."article_categories_link
00671                       WHERE article_id = $articleId";
00672 
00673             return $this->Execute( $query );
00674         }
00675 
00681         function updatePostCategoriesLink( $articleId, $categories )
00682         {
00683             if( !$this->deletePostCategoriesLink( $articleId ))
00684                 return false;
00685 
00686             return $this->addPostCategoriesLink( $articleId, $categories );
00687         }
00688 
00696         function addArticle( &$newArticle )
00697         {
00698             // first, we build up the query
00699             $query = "INSERT INTO ".$this->getPrefix()."articles( user_id,blog_id,status,date,properties, slug )
00700                       VALUES ( ".$newArticle->getUser().",".
00701                       $newArticle->getBlog().",'".
00702                       $newArticle->getStatus()."','".
00703                       $newArticle->getDate()."','".
00704                       serialize($newArticle->getProperties())."','".
00705                       $newArticle->getPostSlug()."');";
00706             // and then we send it to the db
00707             //$this->_db->debug=true;
00708             $result = $this->Execute( $query );
00709 
00710             if( !$result ){
00711                 return false;
00712             }
00713 
00714             // get id of the post from the database
00715             $postId = $this->_db->Insert_ID();
00716             
00717             // save the post text
00718             $newArticle->setId( $postId );
00719             $this->addArticleText( $newArticle );
00720 
00721             // and create the link between the post and its categories?
00722             $this->addPostCategoriesLink( $postId, $newArticle->getCategoryIds());
00723 
00724             // and save the custom fields
00725             $this->addArticleCustomFields( $postId, $newArticle->getBlog(), $newArticle->getFields());
00726 
00727             return $postId;
00728         }
00729         
00737         function addArticleText( $newArticle )
00738         {
00739             $filter = new Textfilter();
00740             $prefix = $this->getPrefix();
00741             $query = "INSERT INTO {$prefix}articles_text
00742                                   (article_id, topic, text, normalized_text, normalized_topic)
00743                       VALUES( '".Db::qstr( $newArticle->getId())."', '".
00744                                 Db::qstr($newArticle->getTopic())."','".
00745                                 Db::qstr($newArticle->getText(false))."','".
00746                                 $filter->normalizeText(Db::qstr($newArticle->getText(false)))."', '".
00747                                 $filter->normalizeText(Db::qstr($newArticle->getTopic()))."')";
00748                                 
00749             return( $this->Execute( $query ));
00750         }
00751         
00758         function getArticleText( $articleId )
00759         {
00760             $prefix = $this->getPrefix();
00761             $query = "SELECT text,topic FROM {$prefix}articles_text
00762                       WHERE article_id = '".Db::qstr($articleId)."'";
00763                       
00764             $result = $this->Execute( $query );
00765             
00766             if( !$result ) 
00767                 return false;
00768                 
00769             $row = $result->FetchRow();
00770             
00771             $result->Close();
00772             
00773             return( $row );         
00774         }
00775         
00782         function updateArticleText( $article )
00783         {
00784             $filter = new Textfilter();
00785             $query = "UPDATE ".$this->getPrefix()."articles_text SET 
00786                         topic = '".Db::qstr($article->getTopic())."'".
00787                      ", text = '".Db::qstr($article->getText(false))."'".
00788                      ", normalized_text = '".$filter->normalizeText(Db::qstr($article->getText(false)))."'".
00789                      ", normalized_topic = '".$filter->normalizeText(Db::qstr($article->getTopic()))."'".
00790                      " WHERE article_id = ".$article->getId().";";
00791             
00792             return($this->Execute( $query ));
00793         }
00794 
00803         function addArticleCustomFields( $artId, $blogId, $fields )
00804         {
00805             $customFields = new CustomFieldsValues();
00806 
00807             foreach( $fields as $field ) {
00808                 $customFields->addCustomFieldValue( $field->getFieldId(), $field->getValue(), $artId, $blogId );
00809             }
00810 
00811             return true;
00812         }
00813 
00820         function updateArticle( $article )
00821         {
00822             // we have to build up the query, which will be pretty long...
00823             $articleDate = Timestamp::getDateWithOffset( $article->getDate(), -($article->getTimeOffset()));
00824 
00825             $query = "UPDATE ".$this->getPrefix()."articles SET id = ".$article->getId().
00826                      ", user_id = ".$article->getUser().
00827                      ", date = '".$articleDate. "'".
00828                      ", blog_id = ".$article->getBlog().
00829                      ", status = '".$article->getStatus()."'".
00830                      ", num_reads = ".$article->getNumReads().
00831                      ", properties = '".serialize($article->getProperties())."'".
00832                      ", slug = '".$article->getPostSlug()."'".
00833                      " WHERE id = ".$article->getId().";";
00834 
00835             $result = $this->Execute( $query );
00836 
00837             // we don't bother doing anything else if the query above failed...
00838             if( !$result )
00839                 return false;
00840                 
00841             // update the article text
00842             $this->updateArticleText( $article );
00843 
00844             if( !$this->updatePostCategoriesLink( $article->getId(), $article->getCategoryIds()))
00845                 return false;
00846 
00847             if( !$this->updateArticleCustomFields( $article->getId(), $article->getBlog(), $article->getFields()))
00848                 return false;
00849 
00850             return true;
00851         }
00852 
00863         function updateArticleCustomFields( $artId, $blogId, $fields )
00864         {
00865             $customFields = new CustomFieldsValues();
00866 
00867             // first remove the values
00868             if( !$customFields->removeArticleCustomFields( $artId ))
00869                 return false;
00870 
00871             foreach( $fields as $field ) {
00872                 $customFields->addCustomFieldValue( $field->getFieldId(), $field->getValue(), $artId, $blogId );
00873             }
00874 
00875             return true;
00876         }
00877 
00887         function updateArticleNumReads( $articleId )
00888         {
00889             // we have to build up the query, which will be pretty long...
00890             $query = "UPDATE ".$this->getPrefix()."articles SET ".
00891                      " num_reads = num_reads+1 ".
00892                      ", date = date ".
00893                      " WHERE id = '".Db::qstr($articleId)."'";
00894 
00895             $result = $this->Execute( $query );
00896 
00897             return $result;
00898         }
00899         
00906         function updateArticleNumReadsByName( $articleName )
00907         {
00908             // we have to build up the query, which will be pretty long...
00909             $query = "UPDATE ".$this->getPrefix()."articles SET ".
00910                      " num_reads = num_reads+1 ".
00911                      ", date = date ".
00912                      " WHERE slug = '".Db::qstr($articleName)."'";
00913 
00914             $result = $this->Execute( $query );
00915 
00916             return $result;
00917         }       
00918 
00939         function deleteArticle( $artId, $userId, $blogId, $forever = false )
00940         {
00941             if( $forever ) {
00942                 $query = "DELETE FROM ".$this->getPrefix()."articles WHERE id = ".$artId." AND user_id = ".$userId." AND blog_id = ".$blogId.";";
00943                 // -- text --
00944                 $this->deleteArticleText( $artId );
00945                 // we also have to remove its comments and trackbacks if the article is being deleted forever
00946                 // -- comments --
00947                 $comments = new ArticleComments();
00948                 $comments->deletePostComments( $artId );
00949                 // -- trackbacks --
00950                 $trackbacks = new Trackbacks();
00951                 $trackbacks->deletePostTrackbacks( $artId );
00952                 // -- post-to-categories mappings --
00953                 $this->deletePostCategoriesLink( $artId );
00954                 // -- custom fields --
00955                 $customFields = new CustomFieldsValues();
00956                 $customFields->removeArticleCustomFields( $artId );
00957             }
00958             else {
00959                 $query = "UPDATE ".$this->getPrefix()."articles SET date = date, status = 3 WHERE id = ".$artId." AND user_id = ".$userId." AND blog_id = ".$blogId.";";
00960             }
00961 
00962             $result = $this->Execute( $query );
00963 
00964             if( !$result )
00965                 return false;
00966 
00967             if( $this->_db->Affected_Rows() == 0 )
00968                 return false;
00969 
00970             return true;
00971         }
00972         
00981         function deleteArticleText( $articleId )
00982         {
00983             $query = "DELETE FROM ".$this->getPrefix()."articles_text WHERE article_id = '".Db::qstr($articleId)."'";
00984             
00985             return( $this->Execute( $query ));
00986         }
00987 
00996         function doesUserOwnArticle( $userinfo, $artid )
00997         {
00998             $article = $this->getArticle( $artid );
00999             $articleOwnerInfo = $article->getUserInfo();
01000 
01001             if( $articleOwnerInfo->getId() == $userinfo->getId())
01002                 return true;
01003             else
01004                 return false;
01005         }
01006 
01014         function getAllArticles( $maxPosts = 0, $date = 0)
01015         {
01016             $query = "SELECT * FROM ".$this->getPrefix()."articles WHERE status = 1";
01017             if( $date > 0 )
01018                 $query .= " AND date < '$date'";
01019 
01020             $query .= " ORDER BY date DESC";
01021 
01022             if( $maxPosts > 0 )
01023                 $query .= " LIMIT 0,".$maxPosts;
01024 
01025             $result = $this->Execute( $query );
01026 
01027             if( !$result )
01028                 return false;
01029 
01030             $posts = Array();
01031             while( $row = $result->FetchRow()) {
01032                 $posts[] = $this->_fillArticleInformation( $row );
01033             }
01034             
01035             $result->Close();            
01036 
01037             return $posts;
01038         }
01039 
01045         function deleteBlogPosts( $blogId )
01046         {
01047             $blogArticles = $this->getBlogArticles( $blogId );
01048 
01049             foreach( $blogArticles as $article ) {
01050                 // the deleteArticle method will also take care of removing comments and
01051                 // trackbacks
01052                 $this->deleteArticle( $article->getId(), $article->getUser(), $article->getBlog(), true );
01053             }
01054 
01055             return true;
01056         }
01057 
01063         function purgePosts()
01064         {
01065             $query = "SELECT * FROM ".$this->getPrefix()."articles WHERE status = 3";
01066 
01067             $result = $this->Execute( $query );
01068             if( !$result )
01069                 return false;
01070 
01071             while( $row = $result->FetchRow()) {
01072                 $this->deleteArticle( $row["id"], $row["user_id"], $row["blog_id"], true );
01073             }
01074             
01075             $result->Close();            
01076 
01077             return true;
01078         }
01079 
01083         function getArticleCategories( $articleId, $blogId = -1 )
01084         {
01085             return $this->categories->getArticleCategories( $articleId, $blogId );
01086         }
01087 
01091         function getArticleCategoryIds( $articleId )
01092         {
01093             $query = "SELECT category_id FROM ".$this->getPrefix()."article_categories_link
01094                       WHERE article_id = $articleId";
01095 
01096             $result = $this->Execute( $query );
01097 
01098             // it's impossible that an article has no categories, but
01099             // we'll bear with it...
01100             if( !$result )
01101                 return Array();
01102 
01103             // otherwise, fetch them
01104             $categories = Array();
01105             while( $row = $result->FetchRow()) {
01106                 $categories[] = $row['category_id'];
01107             }
01108             
01109             $result->Close();            
01110 
01111             return $categories;
01112         }
01113 
01121         function _fillArticleInformation( $query_result, $includeHiddenFields = true )
01122         {
01123             $id = $query_result['id'];
01124             if( isset($this->cache[$id])) {
01125                 return($this->cache[$id]);
01126             }
01127 
01128             // this is a little dirty trick or otherwise the old
01129             // that don't have the 'properties' field will not work
01130             // as they will appear to have comments disabled
01131             if( $query_result['properties'] == "" ) {
01132                 $tmpArray = Array( 'comments_enabled' => true );
01133                 $query_result['properties'] = serialize($tmpArray);
01134             }
01135 
01136             // ---
01137             // this, i do not like... but I couldn't find a more
01138             // "elegant" way to arrange it! This makes this method
01139             // totally dependant on the blog configuration so it basically
01140             // means an additional query every time we fetch an article
01141             // (just in case we didn't have enough!)
01142             // ---
01143 
01144             //
01145             // if there's a time difference applied to all dates, then we'd better
01146             // calculate it here!!
01147             //
01148             $blogId = $query_result['blog_id'];
01149             $blogInfo = $this->blogs->getBlogInfo( $blogId );
01150             $blogSettings = $blogInfo->getSettings();
01151             $timeDiff = $blogSettings->getValue( 'time_offset' );
01152 
01153             // we can use this auxiliary function to help us...
01154             $date = Timestamp::getDateWithOffset( $query_result['date'], $timeDiff );
01155 
01156             $articleCategories = $this->getArticleCategories( $query_result['id'], $query_result['blog_id'] );
01157             $categoryIds = Array();
01158             foreach( $articleCategories as $category )
01159                 array_push( $categoryIds, $category->getId());
01160                 
01161             // get the article text
01162             $postText = $this->getArticleText( $query_result['id'] );
01163 
01164             $article = new Article( $postText['topic'],
01165                                     $postText['text'],
01166                                     $categoryIds,
01167                                     $query_result['user_id'],
01168                                     $query_result['blog_id'],
01169                                     $query_result['status'],
01170                                     $query_result['num_reads'],
01171                                     unserialize($query_result['properties']),
01172                                     $query_result['slug'],
01173                                     $query_result['id'] );
01174                                     
01175             // and fill in all the fields with the information we just got from the db
01176             $article->setDate( $date );
01177             $article->setTimeOffset( $timeDiff