      1: <?php
      2:
      3: // include the config file
      4: if(!isset($config)) {
      5:     require_once '../util/AlphaConfig.inc';
      6:     $config = AlphaConfig::getInstance();
      7:
      8:     require_once $config->get('app.root').'alpha/util/AlphaAutoLoader.inc';
      9: }
     10:
     11: /**
     12:  *
     13:  * Controller used to display a Markdown version of an article
     14:  *
     15:  * @package alpha::controller
     16:  * @since 1.0
     17:  * @author John Collins <dev@alphaframework.org>
     18:  * @version $Id: ViewArticle.php 1573 2012-10-23 13:23:23Z alphadevx $
     19:  * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
     20:  * @copyright Copyright (c) 2012, John Collins (founder of Alpha Framework).
     21:  * All rights reserved.
     22:  *
     23:  * <pre>
     24:  * Redistribution and use in source and binary forms, with or
     25:  * without modification, are permitted provided that the
     26:  * following conditions are met:
     27:  *
     28:  * * Redistributions of source code must retain the above
     29:  *   copyright notice, this list of conditions and the
     30:  *   following disclaimer.
     31:  * * Redistributions in binary form must reproduce the above
     32:  *   copyright notice, this list of conditions and the
     33:  *   following disclaimer in the documentation and/or other
     34:  *   materials provided with the distribution.
     35:  * * Neither the name of the Alpha Framework nor the names
     36:  *   of its contributors may be used to endorse or promote
     37:  *   products derived from this software without specific
     38:  *   prior written permission.
     39:  *
     40:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
     41:  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
     42:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     43:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     44:  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     45:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     46:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     47:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     48:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     49:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     50:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     51:  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     52:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     53:  * </pre>
     54:  *
     55:  */
     56: class ViewArticle extends AlphaController implements AlphaControllerInterface {
     57:     /**
     58:      * The article to be rendered
     59:      *
     60:      * @var ArticleObject
     61:      * @since 1.0
     62:      */
     63:     protected $BO;
     64:
     65:     /**
     66:      * Trace logger
     67:      *
     68:      * @var Logger
     69:      * @since 1.0
     70:      */
     71:     private static $logger = null;
     72:
     73:     /**
     74:      * constructor to set up the object
     75:      *
     76:      * @since 1.0
     77:      */
     78:     public function __construct() {
     79:         self::$logger = new Logger('ViewArticle');
     80:         self::$logger->debug('>>__construct()');
     81:
     82:         global $config;
     83:
     84:         // ensure that the super class constructor is called, indicating the rights group
     85:         parent::__construct('Public');
     86:
     87:         $this->BO = new ArticleObject();
     88:
     89:         self::$logger->debug('<<__construct');
     90:     }
     91:
     92:     /**
     93:      * Handle GET requests
     94:      *
     95:      * @param array $params
     96:      * @since 1.0
     97:      * @throws ResourceNotFoundException
     98:      */
     99:     public function doGET($params) {
    100:         global $config;
    101:
    102:         try{
    103:             // check to see if we need to force a re-direct to the mod_rewrite alias URL for the article
    104:             if($config->get('app.force.mod.rewrite.uls') && basename($_SERVER['PHP_SELF']) == 'ViewArticle.php') {
    105:                 // set the correct HTTP header for the response
    106:                 header('HTTP/1.1 301 Moved Permanently');
    107:
    108:                 header('Location: '.$this->BO->get('URL'));
    109:
    110:                 // we're done here
    111:                 exit;
    112:             }
    113:
    114:             // load the business object (BO) definition
    115:             if (isset($params['oid']) && AlphaValidator::isInteger($params['oid'])) {
    116:                 $this->BO->load($params['oid']);
    117:
    118:                 $BOView = AlphaView::getInstance($this->BO);
    119:
    120:                 // set up the title and meta details
    121:                 $this->setTitle($this->BO->get('title'));
    122:                 $this->setDescription($this->BO->get('description'));
    123:
    124:                 echo AlphaView::displayPageHead($this);
    125:
    126:                 echo $BOView->markdownView();
    127:             }else{
    128:                 throw new IllegalArguementException('No article available to view!');
    129:             }
    130:         }catch(IllegalArguementException $e) {
    131:             self::$logger->error($e->getMessage());
    132:             throw new ResourceNotFoundException($e->getMessage());
    133:         }catch(BONotFoundException $e) {
    134:             self::$logger->warn($e->getMessage());
    135:             throw new ResourceNotFoundException('The article that you have requested cannot be found!');
    136:         }
    137:
    138:         echo AlphaView::displayPageFoot($this);
    139:     }
    140:
    141:     /**
    142:      * Callback used to inject ArticleObject headerContent into the page
    143:      *
    144:      * @return string
    145:      * @since 1.0
    146:      */
    147:     public function during_displayPageHead_callback() {
    148:         return $this->BO->get('headerContent');
    149:     }
    150:
    151:     /**
    152:      * Callback that inserts the CMS level header
    153:      *
    154:      * @return string
    155:      * @since 1.0
    156:      */
    157:     public function insert_CMSDisplayStandardHeader_callback() {
    158:         global $config;
    159:
    160:         $html = '';
    161:
    162:         if($config->get('cms.display.standard.header')) {
    163:             $html.= '<p><a href="'.$config->get('app.url').'">'.$config->get('app.title').'</a> &nbsp; &nbsp;';
    164:             $html.= 'Date Added: <em>'.$this->BO->getCreateTS()->getDate().'</em> &nbsp; &nbsp;';
    165:             $html.= 'Last Updated: <em>'.$this->BO->getUpdateTS()->getDate().'</em> &nbsp; &nbsp;';
    166:             $html.= 'Revision: <em>'.$this->BO->getVersion().'</em></p>';
    167:         }
    168:
    169:         $html.= $config->get('cms.header');
    170:
    171:         return $html;
    172:     }
    173:
    174:     /**
    175:      * Callback used to render footer content, including comments, votes and print/PDF buttons when
    176:      * enabled to do so.
    177:      *
    178:      * @return string
    179:      * @since 1.0
    180:      */
    181:     public function before_displayPageFoot_callback() {
    182:         global $config;
    183:
    184:         $html = '';
    185:
    186:         if($config->get('cms.display.comments'))
    187:             $html .= $this->renderComments();
    188:
    189:         if($config->get('cms.display.tags')) {
    190:             $tags = $this->BO->getPropObject('tags')->getRelatedObjects();
    191:
    192:             if(count($tags) > 0) {
    193:                 $html .= '<p>Tags:';
    194:
    195:                 foreach($tags as $tag)
    196:                     $html .= ' <a href="'.$config->get('app.url').'search/q/'.$tag->get('content').'">'.$tag->get('content').'</a>';
    197:                 $html .= '</p>';
    198:             }
    199:         }
    200:
    201:         if($config->get('cms.display.votes')) {
    202:             $rating = $this->BO->getArticleScore();
    203:             $votes = $this->BO->getArticleVotes();
    204:             $html .= '<p>Average Article User Rating: <strong>'.$rating.'</strong> out of 10 (based on <strong>'.count($votes).'</strong> votes)</p>';
    205:         }
    206:
    207:         if(!$this->BO->checkUserVoted() && $config->get('cms.voting.allowed')) {
    208:             $html .= '<form action="'.$_SERVER['REQUEST_URI'].'" method="post">';
    209:             $html .= '<p>Please rate this article from 1-10 (10 being the best):' .
    210:                     '<select name="user_vote">' .
    211:                     '<option value="1">1' .
    212:                     '<option value="2">2' .
    213:                     '<option value="3">3' .
    214:                     '<option value="4">4' .
    215:                     '<option value="5">5' .
    216:                     '<option value="6">6' .
    217:                     '<option value="7">7' .
    218:                     '<option value="8">8' .
    219:                     '<option value="9">9' .
    220:                     '<option value="10">10' .
    221:                     '</select></p>&nbsp;&nbsp;';
    222:             $temp = new Button('submit','Vote!','voteBut');
    223:             $html .= $temp->render();
    224:
    225:             $html .= AlphaView::renderSecurityFields();
    226:             $html .= '<form>';
    227:         }
    228:
    229:         AlphaDAO::disconnect();
    230:
    231:         if($config->get('cms.allow.print.versions')) {
    232:             $html .= '&nbsp;&nbsp;';
    233:             $temp = new Button("window.open('".$this->BO->get('printURL')."')",'Open Printer Version','printBut');
    234:             $html .= $temp->render();
    235:         }
    236:
    237:         $html .= '&nbsp;&nbsp;';
    238:         if($config->get('cms.allow.pdf.versions')) {
    239:             $html .= '&nbsp;&nbsp;';
    240:             $temp = new Button("document.location = '".FrontController::generateSecureURL("act=ViewArticlePDF&title=".$this->BO->get("title"))."';",'Open PDF Version','pdfBut');
    241:             $html .= $temp->render();
    242:         }
    243:
    244:         // render edit button for admins only
    245:         if (isset($_SESSION['currentUser']) && $_SESSION['currentUser']->inGroup('Admin')) {
    246:             $html .= '&nbsp;&nbsp;';
    247:             $button = new Button("document.location = '".FrontController::generateSecureURL('act=Edit&bo='.get_class($this->BO).'&oid='.$this->BO->getID())."'",'Edit','editBut');
    248:             $html .= $button->render();
    249:         }
    250:
    251:         if($config->get('cms.display.standard.footer')) {
    252:             $html .= '<p>Article URL: <a href="http://'.$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"].'">http://'.$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"].'</a><br>';
    253:             $html .= 'Title: '.$this->BO->get('title').'<br>';
    254:             $html .= 'Author: '.$this->BO->get('author').'</p>';
    255:         }
    256:
    257:         $html .= $config->get('cms.footer');
    258:
    259:         return $html;
    260:     }
    261:
    262:     /**
    263:      * Method to handle POST requests
    264:      *
    265:      * @param array $params
    266:      * @since 1.0
    267:      */
    268:     public function doPOST($params) {
    269:         global $config;
    270:
    271:         try {
    272:             // check the hidden security fields before accepting the form POST data
    273:             if(!$this->checkSecurityFields())
    274:                 throw new SecurityException('This page cannot accept post data from remote servers!');
    275:
    276:
    277:             if(isset($params['voteBut']) && !$this->BO->checkUserVoted()) {
    278:                 $vote = new ArticleVoteObject();
    279:
    280:                 if(isset($params['oid'])) {
    281:                     $vote->set('articleOID', $params['oid']);
    282:                 }else{
    283:                     // load article by title?
    284:                     if (isset($params['title'])) {
    285:                         $title = str_replace('_', ' ', $params['title']);
    286:                     }else{
    287:                         throw new IllegalArguementException('Could not load the article as a title or OID was not supplied!');
    288:                     }
    289:
    290:                     $this->BO = new ArticleObject();
    291:                     $this->BO->loadByAttribute('title', $title);
    292:                     $vote->set('articleOID', $this->BO->getOID());
    293:                 }
    294:
    295:                 $vote->set('personOID', $_SESSION['currentUser']->getID());
    296:                 $vote->set('score', $params['user_vote']);
    297:
    298:                 try {
    299:                     $vote->save();
    300:
    301:                     AlphaDAO::disconnect();
    302:
    303:                     $this->setStatusMessage(AlphaView::displayUpdateMessage('Thank you for rating this article!'));
    304:
    305:                     $this->doGET($params);
    306:                 }catch (FailedSaveException $e) {
    307:                     self::$logger->error($e->getMessage());
    308:                 }
    309:             }
    310:
    311:             if(isset($params['createBut'])) {
    312:                 $comment = new ArticleCommentObject();
    313:
    314:                 // populate the transient object from post data
    315:                 $comment->populateFromPost();
    316:
    317:                 // filter the comment before saving
    318:                 $comment->set('content', InputFilter::encode($comment->get('content')));
    319:
    320:                 try {
    321:                     $success = $comment->save();
    322:
    323:                     AlphaDAO::disconnect();
    324:
    325:                     $this->setStatusMessage(AlphaView::displayUpdateMessage('Thank you for your comment!'));
    326:
    327:                     $this->doGET($params);
    328:                 }catch (FailedSaveException $e) {
    329:                     self::$logger->error($e->getMessage());
    330:                 }
    331:             }
    332:
    333:             if(isset($params['saveBut'])) {
    334:                 $comment = new ArticleCommentObject();
    335:
    336:                 try {
    337:                     $comment->load($params['article_comment_id']);
    338:
    339:                     // re-populates the old object from post data
    340:                     $comment->populateFromPost();
    341:
    342:                     $success = $comment->save();
    343:
    344:                     AlphaDAO::disconnect();
    345:
    346:                     $this->setStatusMessage(AlphaView::displayUpdateMessage('Your comment has been updated.'));
    347:
    348:                     $this->doGET($params);
    349:                 }catch (AlphaException $e) {
    350:                     self::$logger->error($e->getMessage());
    351:                 }
    352:             }
    353:         }catch(SecurityException $e) {
    354:             self::$logger->warn($e->getMessage());
    355:             throw new ResourceNotAllowedException($e->getMessage());
    356:         }
    357:     }
    358:
    359:     /**
    360:      * Method for displaying the user comments for the article.
    361:      *
    362:      * @return string
    363:      * @since 1.0
    364:      */
    365:     private function renderComments() {
    366:         global $config;
    367:
    368:         $html = '';
    369:
    370:         $comments = $this->BO->getArticleComments();
    371:         $comment_count = count($comments);
    372:
    373:         if($config->get('cms.display.comments') && $comment_count > 0) {
    374:             $html .= '<h2>There are ['.$comment_count.'] user comments for this article</h2>';
    375:
    376:             ob_start();
    377:             for($i = 0; $i < $comment_count; $i++) {
    378:                 $view = AlphaView::getInstance($comments[$i]);
    379:                 $view->markdownView();
    380:             }
    381:             $html.= ob_get_clean();
    382:         }
    383:
    384:         if(isset($_SESSION['currentUser']) && $config->get('cms.comments.allowed')) {
    385:             $comment = new ArticleCommentObject();
    386:             $comment->set('articleOID', $this->BO->getID());
    387:
    388:             ob_start();
    389:             $view = AlphaView::getInstance($comment);
    390:             $view->createView();
    391:             $html.= ob_get_clean();
    392:         }
    393:
    394:         return $html;
    395:     }
    396: }
    397:
    398: // now build the new controller
    399: if(basename($_SERVER['PHP_SELF']) == 'ViewArticle.php') {
    400:     $controller = new ViewArticle();
    401:
    402:     if(!empty($_POST)) {
    403:         $controller->doPOST($_REQUEST);
    404:     }else{
    405:         $controller->doGET($_GET);
    406:     }
    407: }
    408:
    409: ?>