Alpha Framework alpha--model
[ class tree: alpha--model ] [ index: alpha--model ] [ all elements ]

Source for file ArticleObject.inc

Documentation is available at ArticleObject.inc

  1. <?php
  2.  
  3. require_once $config->get('sysRoot').'alpha/model/AlphaDAO.inc';
  4. require_once $config->get('sysRoot').'alpha/model/ArticleVoteObject.inc';
  5. require_once $config->get('sysRoot').'alpha/model/ArticleCommentObject.inc';
  6. require_once $config->get('sysRoot').'alpha/model/TagObject.inc';
  7. require_once $config->get('sysRoot').'alpha/controller/front/FrontController.inc';
  8.  
  9. /**
  10.  *
  11.  * An article class for the CMS
  12.  * 
  13.  * @package alpha::model
  14.  * @since 1.0
  15.  * @author John Collins <dev@alphaframework.org>
  16.  * @version $Id: ArticleObject.inc 1453 2011-12-04 15:12:54Z johnc $
  17.  * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
  18.  * @copyright Copyright (c) 2011, John Collins (founder of Alpha Framework).
  19.  *  All rights reserved.
  20.  * 
  21.  *  <pre>
  22.  *  Redistribution and use in source and binary forms, with or
  23.  *  without modification, are permitted provided that the
  24.  *  following conditions are met:
  25.  * 
  26.  *  * Redistributions of source code must retain the above
  27.  *    copyright notice, this list of conditions and the
  28.  *    following disclaimer.
  29.  *  * Redistributions in binary form must reproduce the above
  30.  *    copyright notice, this list of conditions and the
  31.  *    following disclaimer in the documentation and/or other
  32.  *    materials provided with the distribution.
  33.  *  * Neither the name of the Alpha Framework nor the names
  34.  *    of its contributors may be used to endorse or promote
  35.  *    products derived from this software without specific
  36.  *    prior written permission.
  37.  *   
  38.  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  39.  *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  40.  *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  41.  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  42.  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  43.  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  44.  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  45.  *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  46.  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47.  *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  48.  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  49.  *  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  50.  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  51.  *  </pre>
  52.  *  
  53.  */
  54. class ArticleObject extends AlphaDAO {
  55.     /**
  56.      * The article title
  57.      * 
  58.      * @var String 
  59.      * @since 1.0
  60.      */
  61.     protected $title;
  62.     
  63.     /**
  64.      * The article site section
  65.      * 
  66.      * @var DEnum 
  67.      * @since 1.0
  68.      */
  69.     protected $section;
  70.     
  71.     /**
  72.      * The description of the article
  73.      * 
  74.      * @var String 
  75.      * @since 1.0
  76.      */
  77.     protected $description;
  78.     
  79.     /**
  80.      * Optional custom body onload Javascript
  81.      * 
  82.      * @var String 
  83.      * @since 1.0
  84.      */
  85.     protected $bodyOnload;
  86.     
  87.     /**
  88.      * Any custom HTML header content (e.g. Javascript) for the article
  89.      * 
  90.      * @var Text 
  91.      * @since 1.0
  92.      */
  93.     protected $headerContent;
  94.     
  95.     /**
  96.      * The article content
  97.      * 
  98.      * @var Text 
  99.      * @since 1.0
  100.      */
  101.     protected $content;
  102.     
  103.     /**
  104.      * The author of the article
  105.      * 
  106.      * @var String 
  107.      * @since 1.0
  108.      */
  109.     protected $author;
  110.     
  111.     /**
  112.      * A boolean to control whether the artcile is publically accessible or not
  113.      * 
  114.      * @var Boolean 
  115.      * @since 1.0
  116.      */
  117.     protected $published;
  118.     
  119.     /**
  120.      * A Relation containing all of the comments on this article
  121.      *
  122.      * @var Relation 
  123.      * @since 1.0
  124.      */
  125.     protected $comments;
  126.     
  127.     /**
  128.      * A Relation containing all of the votes on this article
  129.      *
  130.      * @var Relation 
  131.      * @since 1.0
  132.      */
  133.     protected $votes;
  134.     
  135.     /**
  136.      * A Relation containing all of the tags on this article
  137.      *
  138.      * @var Relation 
  139.      * @since 1.0
  140.      */
  141.     protected $tags;
  142.     
  143.     /**
  144.      * An array of all of the attributes on this BO which are tagged
  145.      *  
  146.      * @var array 
  147.      * @since 1.0
  148.      */
  149.     protected $taggedAttributes = array('title''description''content');
  150.     
  151.     /**
  152.      * Path to a .text file where the content of this article is stored (optional)
  153.      * 
  154.      * @var string 
  155.      * @since 1.0
  156.      */
  157.     private $filePath;
  158.     
  159.     /**
  160.      * An array of data display labels for the class properties
  161.      * 
  162.      * @var array 
  163.      * @since 1.0
  164.      */
  165.     protected $dataLabels = array("OID"=>"Article ID#","title"=>"Title","section"=>"Site Section","description"=>"Description","bodyOnload"=>"Body onload Javascript","content"=>"Content","headerContent"=>"HTML Header Content","author"=>"Author","created_ts"=>"Date Added","updated_ts"=>"Date of last Update","published"=>"Published","URL"=>"URL","printURL"=>"Printer version URL","comments"=>"Comments","votes"=>"Votes","tags"=>"Tags");
  166.     
  167.     /**
  168.      * The name of the database table for the class
  169.      * 
  170.      * @var string 
  171.      * @since 1.0
  172.      */
  173.     const TABLE_NAME = 'Article';
  174.     
  175.     /**
  176.      * The URL for this article (transient)
  177.      * 
  178.      * @var string 
  179.      * @since 1.0
  180.      */
  181.     protected $URL;
  182.     
  183.     /**
  184.      * The print URL for this article (transient)
  185.      * 
  186.      * @var string 
  187.      * @since 1.0
  188.      */
  189.     protected $printURL;
  190.     
  191.     /**
  192.      * Trace logger
  193.      * 
  194.      * @var Logger 
  195.      * @since 1.0
  196.      */
  197.     private static $logger null;
  198.     
  199.     /**
  200.      * The constructor which sets up some housekeeping attributes
  201.      * 
  202.      * @since 1.0
  203.      */
  204.     public function __construct({
  205.         self::$logger new Logger('ArticleObject');
  206.         
  207.         // ensure to call the parent constructor
  208.         parent::__construct();
  209.         
  210.         $this->title = new String();
  211.         $this->title->setHelper('Please provide a title for the article.');
  212.         $this->title->setSize(100);
  213.         $this->title->setRule("/\w+/");
  214.         
  215.         $this->section = new DEnum('ArticleObject::section');        
  216.         
  217.         $this->description = new String();
  218.         $this->description->setHelper('Please provide a brief description of the article.');
  219.         $this->description->setSize(200);
  220.         $this->description->setRule("/\w+/");
  221.         $this->bodyOnload = new String();        
  222.         $this->content = new Text();
  223.         $this->content->setHelper('Please provide some content for the article.');
  224.         $this->content->setRule("/\w+/");
  225.         $this->headerContent = new Text();        
  226.         $this->author = new String();
  227.         $this->author->setHelper('Please state the name of the author of this article');
  228.         $this->author->setSize(70);
  229.         $this->author->setRule("/\w+/");
  230.         $this->published = new Boolean(0);
  231.         
  232.         $this->comments = new Relation();
  233.         $this->markTransient('comments');
  234.         $this->comments->setValue($this->OID);
  235.         $this->comments->setRelatedClass('ArticleCommentObject');
  236.         $this->comments->setRelatedClassField('articleOID');
  237.         $this->comments->setRelatedClassDisplayField('content');
  238.         $this->comments->setRelationType('ONE-TO-MANY');
  239.         
  240.         $this->votes = new Relation();
  241.         $this->markTransient('votes');
  242.         $this->votes->setValue($this->OID);
  243.         $this->votes->setRelatedClass('ArticleVoteObject');
  244.         $this->votes->setRelatedClassField('articleOID');
  245.         $this->votes->setRelatedClassDisplayField('score');
  246.         $this->votes->setRelationType('ONE-TO-MANY');
  247.         
  248.         $this->tags = new Relation();        
  249.         $this->markTransient('tags');
  250.         $this->tags->setRelatedClass('TagObject');
  251.         $this->tags->setRelatedClassField('taggedOID');
  252.         $this->tags->setRelatedClassDisplayField('content');
  253.         $this->tags->setRelationType('ONE-TO-MANY');
  254.         $this->tags->setTaggedClass(get_class($this));
  255.         $this->tags->setValue($this->OID);
  256.         
  257.         $this->URL = '';
  258.         $this->printURL = '';
  259.         // mark the URL attributes as transient
  260.         $this->markTransient('URL');
  261.         $this->markTransient('printURL');
  262.         
  263.         // mark title as unique
  264.         $this->markUnique('title');
  265.         
  266.         $this->markTransient('filePath');
  267.         $this->markTransient('taggedAttributes');
  268.     }
  269.     
  270.     /**
  271.      * After creating a new ArticleObject, tokenize the description field to form a set
  272.      * of automated tags and save them.
  273.      * 
  274.      * @since 1.0
  275.      */
  276.     protected function after_save_callback({
  277.         if($this->getVersion(== && $this->tags instanceof Relation{
  278.             // update the empty tags values to reference this OID
  279.             $this->tags->setValue($this->OID);
  280.             
  281.             foreach($this->taggedAttributes as $tagged{
  282.                 $tags TagObject::tokenize($this->get($tagged)get_class($this)$this->getOID());
  283.                 foreach($tags as $tag{
  284.                     try {
  285.                         $tag->save();
  286.                     }catch(ValidationException $e){
  287.                         /*
  288.                          * The unique key has most-likely been violated because this BO is already tagged with this
  289.                          * value, so we can ignore in this case.
  290.                          */
  291.                     }
  292.                 }
  293.             }
  294.         }
  295.     }
  296.     
  297.     /**
  298.      * Set up the transient URL attributes for the artcile after it has loaded
  299.      * 
  300.      * @since 1.0
  301.      */
  302.     protected function after_loadByAttribute_callback({
  303.         $this->after_load_callback();
  304.     }
  305.     
  306.     /**
  307.      * Set up the transient URL attributes for the article after it has loaded
  308.      * 
  309.      * @since 1.0
  310.      */
  311.     protected function after_load_callback({
  312.         global $config;
  313.         global $front;
  314.         
  315.         // check the config to see if we are using mod_rewrite
  316.         if($config->get('sysUseModRewrite')) {
  317.             // check to see if an alias is registered for the view_article_title controller, otherwise use the long URL version
  318.             if(isset($front&& $front->hasAlias('ViewArticleTitle')) {
  319.                 $alias $front->getControllerAlias('ViewArticleTitle');
  320.                 
  321.                 $this->URL = $config->get('sysURL').$alias.'/'.str_replace(' ''_'$this->title->getValue());
  322.             }else{
  323.                 $this->URL = $config->get('sysURL').'ViewArticleTitle/title/'.str_replace(' ''_'$this->title->getValue());
  324.             }
  325.         }else{
  326.             $this->URL = $config->get('sysURL').'alpha/controller/ViewArticle.php?oid='.$this->getID();
  327.         }
  328.         
  329.         // now set up the print version URL
  330.         if($config->get('sysUseModRewrite')) {
  331.             // check to see if an alias is registered for the view_article_title controller, otherwise use the long URL version
  332.             if(isset($front&& $front->hasAlias('ViewArticlePrint')) {
  333.                 $alias $front->getControllerAlias('ViewArticlePrint');
  334.                 
  335.                 $this->printURL = $config->get('sysURL').$alias.'/'.str_replace(' ''_'$this->title->getValue());
  336.             }else{
  337.                 $this->printURL = $config->get('sysURL').'ViewArticlePrint/title/'.str_replace(' ''_'$this->title->getValue());
  338.             }
  339.         }else{
  340.             $this->printURL = $config->get('sysURL').'alpha/controller/ViewArticlePrint.php?title='.$this->title->getValue();
  341.         }
  342.         
  343.         $this->comments->setValue($this->OID);
  344.         $this->votes->setValue($this->OID);
  345.     }
  346.     
  347.     /**
  348.      * Gets an array of the OIDs of the most recent articles added to the system (by date), from the newest
  349.      * article to the amount specified by the $limit
  350.      * 
  351.      * @return array 
  352.      * @since 1.0
  353.      * @throws AlphaException
  354.      */
  355.     public function loadRecentWithLimit($limit){
  356.         $denum new DEnum('ArticleObject::section');
  357.         $excludeID $denum->getOptionID('Main');
  358.         
  359.         $sqlQuery "SELECT OID FROM ".$this->getTableName()." WHERE published='1' AND section!='$excludeID' ORDER BY dateAdded DESC LIMIT 0, $limit;";        
  360.  
  361.         $result $this->query($sqlQuery);
  362.         
  363.         $OIDs array();
  364.         
  365.         foreach($result as $row)
  366.             array_push($OIDs$row['OID']);
  367.         
  368.         return $OIDs;
  369.     }
  370.     
  371.     /**
  372.      * Generates the location of the attachments folder for this article
  373.      * 
  374.      * @return string 
  375.      * @since 1.0
  376.      */
  377.     public function getAttachmentsLocation({
  378.         global $config;
  379.         
  380.         return $config->get('sysRoot').'attachments/article_'.$this->getID();
  381.     }
  382.     
  383.     /**
  384.      * Generates the URL of the attachments folder for this article
  385.      * 
  386.      * @return string 
  387.      * @since 1.0
  388.      */
  389.     public function getAttachmentsURL({
  390.         global $config;
  391.         
  392.         return $config->get('sysURL').'attachments/article_'.$this->getID();
  393.     }
  394.     
  395.     /**
  396.      * Generates a secure URL for downloading an attachment file via the ViewAttachment controller
  397.      * 
  398.      * @param string $filename 
  399.      * @since 1.0
  400.      */
  401.     public function getAttachmentSecureURL($filename{
  402.         global $config;
  403.         
  404.         return FrontController::generateSecureURL('act=ViewAttachment&dir='.$this->getAttachmentsLocation().'&filename='.$filename);
  405.     }
  406.     
  407.     /**
  408.      * Creates the attachment folder for the article on the server.
  409.      * 
  410.      * @since 1.0
  411.      * @throws AlphaException
  412.      */
  413.     public function createAttachmentsFolder({
  414.         // create the attachment directory for the article
  415.         try{
  416.             mkdir($this->getAttachmentsLocation());
  417.         }catch (Exception $e{
  418.             throw new AlphaException('Unable to create the folder ['.$this->getAttachmentsLocation().'] for the article.');
  419.         }
  420.             
  421.         // ...and set write permissions on the folder
  422.         try{
  423.             chmod($this->getAttachmentsLocation()0777);
  424.         }catch (Exception $e{
  425.             throw new AlphaException('Unable to set write permissions on the folder ['.$this->getAttachmentsLocation().'].');
  426.         }
  427.     }
  428.     
  429.     /**
  430.      * Method for returning the calculated score for this article
  431.      * 
  432.      * @return double 
  433.      * @since 1.0
  434.      */
  435.     public function getArticleScore({
  436.         $votes $this->getArticleVotes();
  437.         
  438.         $score 0;
  439.         $total_score 0;
  440.         $vote_count count($votes);
  441.         
  442.         for($i 0$i $vote_count$i++){
  443.             $total_score += $votes[$i]->get('score');
  444.         }
  445.         
  446.         if($vote_count 0)
  447.         $score $total_score/$vote_count;
  448.         
  449.         return sprintf("%01.2f"$score);
  450.     }
  451.     
  452.     /**
  453.      * Method for fetching all of the votes for this article
  454.      * 
  455.      * @return array An array of ArticleVoteObject objects
  456.      * @since 1.0
  457.      */
  458.     public function getArticleVotes({
  459.         $votes $this->votes->getRelatedObjects();
  460.         
  461.         return $votes;
  462.     }
  463.     
  464.     /**
  465.      * Method to determine if the logged-in user has already voted for this article
  466.      * 
  467.      * @return boolean True if they have voted already, false otherwise
  468.      * @since 1.0
  469.      * @throws AlphaException
  470.      */
  471.     public function checkUserVoted({
  472.         // just going to return true if nobody is logged in
  473.         if (!isset($_SESSION['currentUser']))
  474.             return true;
  475.         
  476.         $userID $_SESSION['currentUser']->getID();
  477.         
  478.         $vote new ArticleVoteObject();
  479.         
  480.         $sqlQuery "SELECT COUNT(*) AS usersVote FROM ".$vote->getTableName()." WHERE articleOID='".$this->OID."' AND personOID='".$userID."';";        
  481.  
  482.         $result $this->query($sqlQuery);
  483.         
  484.         if(!isset($result[0])) {
  485.             throw new AlphaException('Failed to check if the current user voted for the article ['.$this->OID.'], query ['.$sqlQuery.']');
  486.             return false;
  487.         }
  488.         
  489.         $row $result[0];
  490.         
  491.         if($row['usersVote'== "0")
  492.             return false;
  493.         else
  494.             return true;            
  495.     }
  496.     
  497.     /**
  498.      * Method for fetching all of the comments for this article
  499.      * 
  500.      * @return array An array of ArticleCommentObject objects
  501.      * @since 1.0
  502.      */
  503.     public function getArticleComments({
  504.         $comments $this->comments->getRelatedObjects();        
  505.         
  506.         return $comments;
  507.     }
  508.     
  509.     /**
  510.      * Loads the content of the ArticleObject from the specified file path
  511.      * 
  512.      * @param $filePath 
  513.      * @since 1.0
  514.      * @throws FileNotFoundException
  515.      */
  516.     public function loadContentFromFile($filePath{
  517.         try{
  518.             $this->content->setValue(file_get_contents($filePath));
  519.             $this->filePath $filePath;
  520.         }catch (Exception $e{
  521.             throw new FileNotFoundException($e->getMessage());
  522.         }
  523.     }
  524.     
  525.     /**
  526.      * Returns true if the article content was loaded from a .text file, false otherwise.
  527.      * 
  528.      * @return boolean 
  529.      * @since 1.0
  530.      */
  531.     public function isLoadedFromFile({
  532.         return ($this->filePath == '' falsetrue);
  533.     }
  534.     
  535.     /**
  536.      * Returns the timestamp of when the content .text file for this article was last
  537.      * modified.
  538.      * 
  539.      * @return string 
  540.      * @since 1.0
  541.      * @throws FileNotFoundException
  542.      */
  543.     public function getContentFileDate({
  544.         if($this->filePath != ''{
  545.             try{                
  546.                 return date("Y-m-d H:i:s"filemtime($this->filePath));
  547.             }catch (Exception $e{
  548.                 throw new FileNotFoundException($e->getMessage());
  549.             }
  550.         }else{
  551.             throw new FileNotFoundException('Error trying to access an article content file when none is set!');
  552.         }
  553.     }
  554. }
  555.  
  556. ?>

Documentation generated on Tue, 13 Dec 2011 20:26:26 +0000 by phpDocumentor 1.4.3