matteosister avatar matteosister committed 5e7148b

refactored for 1.6

Comments (0)

Files changed (5)

-=======================
+-----------------------
 sfPropel15RatablePlugin
-=======================
+-----------------------
 
-This is a ratable behaviour for propel 1.5 and symfony 1.x
+A behaviour for propel 1.5/1.6 and symfony 1.4.x to rate your objects
+
+How to install
+--------------
+
+- add this plugin as a submodule
+
+    git submodule add git://github.com/matteosister/sfPropel15RatableBehaviorPlugin.git plugins/sfPropel15RatableBehaviorPlugin
+
+- enable the plugin in your **ProjectConfiguration** class
+
+*config/ProjectConfiguration.class.php*
+
+::
+
+    <?php
+
+    require_once dirname(__FILE__) . '/../lib/vendor/symfony/autoload/sfCoreAutoload.class.php';
+    sfCoreAutoload::register();
+
+    class ProjectConfiguration extends sfProjectConfiguration
+    {
+      public function setup()
+      {
+        // ...
+        $this->enablePlugins('sfPropel15RatableBehaviorPlugin');
+        // ...
+      }
+    }
+
+- add the **ratable** behavior to a class in your schema file
+
+*config/schema.xml*
+
+::
+
+    <table name="article">
+        <behavior name="ratable" />
+        <!-- ... -->
+    </table>
+
+- rebuild your model
+
+::
+
+    php symfony propel:build-all
+
+
+
+Columns And Method generated
+----------------------------
+
+The behavior **adds two column to the object**. The average rating, and the total number of votes.
+Here is a full parameters specification with default values.
+
+::
+
+    <behavior name="ratable">
+        <!-- the db name of the average column -->
+        <parameter name="average_column" value="the_average"></parameter>
+        <!-- the php name of the average column -->
+        <parameter name="average_column_phpname" value="Average"></parameter>
+        <!-- the db name of the votes number column -->
+        <parameter name="nb_votes_column" value="ratable_nb_votes"></parameter>
+        <!-- the php name of the votes number column -->
+        <parameter name="nb_votes_column_phpname" value="NbVotes"></parameter>
+        <!-- the average precision  -->
+        <parameter name="precision" value="1"></parameter>
+    </behavior>
+
+The precision value is passed to the php round function to store and retrieve average from db
+
+[php function round] http://it.php.net/manual/en/function.round.php
+
+In the base class of your object model you'll find two new methods:
+
+::
+
+    public function getRating($max = 5, $precision = 1) // $max and $precision default values comes from the schema parameters
+    public function setRating($rating)
+
+see the class comments for reference
+
+How to use
+----------
+
+::
+    
+    <?php
+    $article = new Article(); // nb_votes: 0, avg: null
+
+    $article->setRating(3); // you need to call the save() method to actually write the data to db.
+    $article->save() // nb_votes: 1, avg: 3
+
+    $article->setRating(4);
+    $article->save(); // nb_votes: 2, avg: 3.5
+
+    $article->getRating(); // 3.5 out of 5
+    $article->getRating(10); // 7 out of 10
+    $article->getRating(5, 0); // 4 out of 5

lib/behavior/RatableBehavior.php

  */
 class RatableBehavior extends Behavior
 {
-  protected $parameters = array(
-  );
+    protected $parameters = array(
+        'average_column'  => 'ratable_average',
+        'average_column_phpname' => 'Average',
+        'nb_votes_column' => 'ratable_nb_votes',
+        'nb_votes_column_phpname' => 'NbVotes',
+        'precision'       => 1,
+        'max_vote'        => 5
+    );
 
+    /**
+    * Add the two column to the table
+    */
+	public function modifyTable()
+	{
+		if(!$this->getTable()->containsColumn($this->getParameter('average_column'))) {
+			$this->getTable()->addColumn(array(
+				'name' => $this->getParameter('average_column'),
+                'phpName' => $this->getParameter('average_column_phpname'),
+				'type' => PropelTypes::FLOAT
+			));
+		}
 
-  public function objectMethods()
-  {
-    $script = '';
-    $script .= $this->generateSetRatingMethod();
-    $script .= $this->generateGetRatingMethod();
-    return $script;
-  }
+        if(!$this->getTable()->containsColumn($this->getParameter('nb_votes_column'))) {
+			$this->getTable()->addColumn(array(
+				'name' => $this->getParameter('nb_votes_column'),
+                'phpName' => $this->getParameter('nb_votes_column_phpname'),
+				'type' => PropelTypes::INTEGER
+			));
+		}
+	}
 
+    /**
+	 * Get the getter of the average column of the behavior
+	 *
+	 * @return string The related getter, e.g. 'getAverage'
+	 */
+	protected function getAverageColumnGetter()
+	{
+		return 'get' . $this->getColumnForParameter('average_column')->getPhpName();
+	}
 
+	/**
+	 * Get the setter of the average column of the behavior
+	 *
+	 * @return string The related setter, e.g. 'setAverage'
+	 */
+	protected function getAverageColumnSetter()
+	{
+		return 'set' . $this->getColumnForParameter('average_column')->getPhpName();
+	}
 
-  protected function generateSetRatingMethod()
-  {
-    $table = new Table();
-    $table = $this->getTable();
-    $rateTable = $this->getTable()->getDatabase()->getTable($this->getParameter('ratable'));
-    return "
-/**
- * Rate a propel object with ratable behavior
- *
- * @return average rating if vote is ok, false for duplicate votes.
- */
-public function setRating(\$vote, \$user_id = null, PropelPDO \$con = null) {
-  if (!in_array(\$vote, array(1, 2, 3, 4, 5))) {
-    throw new InvalidArgumentException('You must provide a vote from 1 to 5, no float number allowed');
-  }
+    /**
+	 * Get the getter of the average column of the behavior
+	 *
+	 * @return string The related getter, e.g. 'getAverage'
+	 */
+	protected function getNbVotesColumnGetter()
+	{
+		return 'get' . $this->getColumnForParameter('nb_votes_column')->getPhpName();
+	}
+
+	/**
+	 * Get the setter of the average column of the behavior
+	 *
+	 * @return string The related setter, e.g. 'setAverage'
+	 */
+	protected function getNbVotesColumnSetter()
+	{
+		return 'set' . $this->getColumnForParameter('nb_votes_column')->getPhpName();
+	}
+
+	/**
+	 * Add code in ObjectBuilder::preSave
+	 *
+	 * @return string The code to put at the hook
+	 */
+	public function preInsert($builder)
+	{
+        $script = "
+\$this->{$this->getNbVotesColumnSetter()}(0);
+";
 
-  // no need to check for vote consistency
-  if (\$user_id === null) {
-    \$rate = new sfRatable();
-    \$rate->setRatableModel('{$table->getPhpName()}');
-    \$rate->setRatableId(\$this->id);
-    \$rate->setRating(\$vote);
-    \$rate->save();
-    return \$this->getRating();
-  }
+		return $script;
+	}
 
-  \$alreadyVoted = sfRatableQuery::create()
-    ->filterByUserId(\$user_id)
-    ->filterByRatableModel('{$table->getPhpName()}')
-    ->filterByRatableId(\$this->id)
-    ->count() == 1;
-  if (\$alreadyVoted) {
-    return false;
-  }
+    public function objectMethods()
+    {
+        $script = '';
+        $script .= $this->generateSetRatingMethod();
+        $script .= $this->generateGetRatingMethod();
+        return $script;
+    }
 
-  \$rate = new sfRatable();
-  \$rate->setUserId(\$user_id);
-  \$rate->setRatableModel('{$table->getPhpName()}');
-  \$rate->setRatableId(\$this->getId());
-  \$rate->setRating(\$vote);
-  \$rate->save();
-  return \$this->getRating();
+
+
+    protected function generateSetRatingMethod()
+    {
+        $precision = $this->parameters['precision'];
+        return "
+/**
+* Rate a propel object with ratable behavior
+*/
+public function setRating(\$rating) {
+    if (!is_int(\$rating)) {
+        throw new InvalidArgumentException('You must provide an integer to rate an object');
+    }
+    if (!in_array(\$rating, array(1, 2, 3, 4, 5))) {
+        throw new InvalidArgumentException('You must provide a vote from 1 to 5, no float number allowed');
+    }
+
+    if (null === \$this->{$this->getAverageColumnGetter()}()) {
+        \$newSum = \$rating;
+    } else {
+        \$newSum = (\$this->{$this->getAverageColumnGetter()}() * \$this->{$this->getNbVotesColumnGetter()}()) + \$rating;
+    }
+    \$this->{$this->getNbVotesColumnSetter()}(\$this->{$this->getNbVotesColumnGetter()}() + 1);
+    \$this->{$this->getAverageColumnSetter()}(round(\$newSum / \$this->{$this->getNbVotesColumnGetter()}(), {$precision}));
 }
 ";
-  }
+    }
 
-  protected function generateGetRatingMethod()
-  {
-    $rateTable = $this->getTable()->getDatabase()->getTable($this->getParameter('ratable'));
-    $table = $this->getTable();
-    return "
+    protected function generateGetRatingMethod()
+    {
+        $precision = $this->parameters['precision'];
+        $maxVote = $this->parameters['max_vote'];
+        return "
 /**
  * Get the average rate for a Propel object with ratable behavior
- * @int \$max      The maximum vote
- * @bool \$round   Round result
+ * @int \$max          The maximum vote
+ * @bool \$precision   Precision value for the 'round' php function
  *
  * @return \$vote or null
  */
-public function getRating(\$max = 5, \$round = false) {
-  if (\$max < 5) {
-    throw new InvalidArgumentException('The minimum value for \$max in getRating() method should be >= 5');
-  }
-
-  \$ratables = sfRatableQuery::create()
-    ->filterByRatableModel('{$table->getPhpName()}')
-    ->filterByRatableId(\$this->id)
-    ->find();
-  if (count(\$ratables) == 0) {
-    return null;
-  }
-  \$sum = 0;
-  foreach (\$ratables as \$ratable) {
-    \$sum += \$ratable->getRating();
-  }
-  \$avg = (\$sum / count(\$ratables)) * (\$max / 5);
-  return \$round ? round(\$avg) : \$avg;
+public function getRating(\$max = {$maxVote}, \$precision = {$precision}) {
+    return null === \$this->{$this->getAverageColumnGetter()}() ? null : round((\$this->{$this->getAverageColumnGetter()}() * \$max) / 5, \$precision);
 }
 ";
-  }
+    }
 }
 

lib/model/sfRatable.php

  *
  * 
  *
- * This class was autogenerated by Propel 1.5.3-dev on:
+ * This class was autogenerated by Propel 1.6.0-dev on:
  *
- * Tue Jul  6 17:15:10 2010
+ * Mon Feb  7 23:32:46 2011
  *
  * You should add additional methods to this class to meet the
  * application requirements.  This class will only be generated as

lib/model/sfRatablePeer.php

  *
  * 
  *
- * This class was autogenerated by Propel 1.5.3-dev on:
+ * This class was autogenerated by Propel 1.6.0-dev on:
  *
- * Tue Jul  6 17:15:10 2010
+ * Mon Feb  7 23:32:46 2011
  *
  * You should add additional methods to this class to meet the
  * application requirements.  This class will only be generated as

lib/model/sfRatableQuery.php

  *
  * 
  *
- * This class was autogenerated by Propel 1.5.3-dev on:
+ * This class was autogenerated by Propel 1.6.0-dev on:
  *
- * Tue Jul  6 17:15:10 2010
+ * Mon Feb  7 23:32:46 2011
  *
  * You should add additional methods to this class to meet the
  * application requirements.  This class will only be generated as
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.