= sfPropelVersionableBehaviorPlugin plugin = The `sfPropelVersionableBehaviorPlugin` is a symfony plugin that provides versioning capabilities to any Propel object. == Features == * Fully unit tested * Revert objects to previous versions easily * Conditional versioning == Installation == * Install the plugin {{{ symfony plugin-install http://plugins.symfony-project.com/sfPropelVersionableBehaviorPlugin }}} * Enable Propel behavior support in `propel.ini`: {{{ propel.builder.AddBehaviors = true }}} * Add necessary fields to your each of your model tables that you want to make versionable: {{{ #!xml <!-- schema.xml --> <column name="uuid" type="CHAR" size="36" required="true" /> <column name="version" type="INTEGER" size="11" required="true" /> or <!-- schema.yml --> uuid: { type: char, size: 36, required: true } version: { type: integer, size: 11, required: true } }}} * Rebuild your database and model (the plugin uses two tables to store object version history) {{{ #!sh > php symfony propel-build-all }}} * Enable the behavior for the Propel models that you want to extend. For instance, to extend an `Article` Propel class: {{{ #!php <?php // lib/model/Article.php class Article { } $columns_map = array('uuid' => ArticlePeer::UUID, 'version' => ArticlePeer::VERSION); sfPropelBehavior::add('Article', array('versionable' => array('columns' => $columns_map))); }}} Column map values mean: * uuid : Model column holding resource's universally unique identifier (behavior takes care of generating these) * version : Model column holding resource's current version number == Usage == === Reverting to a previous version === {{{ #!php <?php $article = new Article(); $article->setTitle('First version of article'); $article->save(); // $article->getVersion() == 1 $article->setTitle('Second version of article'); $article->save(); // $article->getVersion() == 2 $article->toVersion(1); // $article->getTitle() == 'First version of article' $article->save(); // $article->getVersion() == 3 }}} === Retrieving a resource version history === {{{ #!php <?php foreach ($article->getAllVersions() as $version) { $history_article = $version->getResourceInstance(); echo sprintf("Version %d title : %s\n", $history_article->getVersion(), $history_article->getTitle()); } /* * Outputs: * * Version 1 title: First version of article * Version 2 title: Second version of article * Version 3 title: First version of article */ }}} === Conditional versioning === You may not want to have a new version of resource created each time it is saved. Just add a `versionConditionMet()` method to your stub class. It is called each time object's `save()`. No version is created if it returns false. Example : {{{ #!php <?php // lib/model/Article.php public function versionConditionMet() { return $this->getTitle() != 'do not version me'; } }}} {{{ #!php <?php $article = new Article(); $article->setTitle('New article'); $article->save(); // article is saved and a new version is created $article->setTitle('do not version me'); $article->save(); // article is saved, no new version is created }}} It is possible to specify a different `versionConditionMet()` method name by defining it when registring behavior : {{{ #!php <?php sfPropelBehavior::add('Article', array('versionable' => array('columns' => $columns_map, 'conditional' => 'myMethod'))); }}} It is possible to change this method at runtime : {{{ #!php <?php $previous_method = sfPropelVersionableBehavior::setVersionConditionMethod('myMethod'); }}} == Public API == === Object API === Enabling the behaviors adds / modifies the following method to the Propel objects : * `void save()`: Adds a new version to resource's version history * `void delete()`: Deletes resource's version history * `void toVersion(integer $version_number)`: Populates resource properties with values from the requested version * `ResourceVersion getLastVersion()`: Returns resource's last version * `array getAllVersions()`: Returns all resource versions in an array === !ResourceVersion API === * `BaseObject getResourceInstance()`: Returns resource instance populated with attributes from the version * `int getNumber()`: Returns the version number of the version object === sfPropelVersionableBehavior API === * (static) `string setVersionConditionMethod(string $method_name)`: Sets object method used to decide if a new version should be created * (static) `string getVersionConditionMethod()`: Returns version condition method name == Roadmap == === 0.3 === * Add unit tests to check version_attributes deletion * Make plugin compatible with sfPropel's i18n capabilities * Replace uuid by a simple composite key class name + id == Changelog == === Trunk === === 2008-02-08 | 0.2.3 alpha === * francois: Fixed error when using a version column different than 'version' === 2008-02-06 | 0.2.2 alpha === * francois: Made the doc more explicit about multiple models (fixes #1820) * francois: Removed need for hardcoded foreign key (fixes #1562) * francois: Switched plugin schema to YAML * francois: Made the unit tests more adaptable === 2007-16-03 | 0.2.1 alpha === * #1563 : does not create a version if YourClass::versionConditionMet() is not found (madman) * #1564 : crashes while creating a new version if no prior version exists (madman) * Syntax highlighting in README * added `sfPropelVersionableBehavior::getVersionConditionMethod()` and `sfPropelVersionableBehavior::setVersionConditionMethod()` methods * enhanced inner management of conditional versioning * updated unit tests and docs accordingly === 2007-02-17 | 0.2.0 alpha === * made version number management more reliable * new `getLastVersion()` method * implemented conditional versioning * updated docs and unit tests accordingly === 2007-02-17 | 0.1.0 alpha === Initial public release.