Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Major update... maybe this is version Alpha 1? All that is left is in…

…clusion of formatter hooks and full testing.

Rewrote the 1N and NN related changelogs methods; They now rely 100% on Propel's introspection API instead of the ncClassFinder (which was removed). However, M:M relations will only work with Propel 1.5 and up.

Other small optimizations and fixes were introduced, and the signature of Behavior::getChangeLog() was changed to have the connection object passed at the end (potentially BC break).

A skeletal test for ncPropelChangeLogBehavior.class.php was added
  • Loading branch information...
commit 20d9c4fd4cae146750b2bccb13851292d1904523 1 parent 6b5843e
@VanTanev authored
View
1  .gitignore
@@ -6,5 +6,6 @@ lib/model/ncChangeLogEntryQuery.php
test/functional/fixtures/data/sql
test/functional/fixtures/data/database.sqlite
test/functional/fixtures/plugins/nc*
+test/functional/fixtures/lib/model/*Query*
test/functional/fixtures/log
test/functional/fixtures/cache
View
208 lib/behavior/ncPropelChangeLogBehavior.class.php
@@ -111,25 +111,9 @@ public function postDelete(BaseObject $object, $con = null)
* @param PropelPDO $con
* @return Array of ncChangeLogEntry
*/
- public function getChangeLog(BaseObject $object, Criteria $criteria = null, PropelPDO $con = null, $transformToAdapters = true)
+ public function getChangeLog(BaseObject $object, Criteria $criteria = null, $transformToAdapters = true, PropelPDO $con = null)
{
- return ncChangeLogEntryPeer::getChangeLogByPKandClassName($object->getPrimaryKey(), get_class($object), $criteria, $con, $transformToAdapters);
- }
-
-
- public static function getRelatedAdapters($tables)
- {
- $results = array();
-
- foreach ($tables as $t => $objects)
- {
- foreach ($objects as $f => $object)
- {
- $results[$t][$f] = $object->getAdapter();
- }
- }
-
- return $results;
+ return ncChangeLogEntryPeer::getChangeLogByPKandClassName($object->getPrimaryKey(), get_class($object), $criteria, $transformToAdapters, $con);
}
@@ -146,45 +130,43 @@ public static function getRelatedAdapters($tables)
*
* @return Array of ncChangeLogEntry
*/
- public function get1NRelatedChangeLog(BaseObject $object, $from_date = null, $transformToAdapters = true)
+ public function get1NRelatedChangeLog(BaseObject $object, $from_date = null, $transformToAdapters = true, PropelPDO $con = null)
{
+ /** @var ColumnMap */ $col;
+ /** @var TableMap */ $tableMap;
+
$relatedChangeLog = array();
- if (!is_null($object))
+ $class = get_class($object);
+ $peer = constant($class . '::PEER');
+ $tableMap = call_user_func(array($peer , 'getTableMap'));
+
+ $criteria = new Criteria();
+ if (!is_null($from_date))
{
- $class = get_class($object);
- $peer = constant($class.'::PEER');
- $tableMap = call_user_func(array($peer , 'getTableMap'));
+ $criteria->add(ncChangeLogEntryPeer::CREATED_AT, $from_date, Criteria::GREATER_THAN);
+ }
- foreach ($tableMap->getColumns() as $c)
+ foreach ($tableMap->getColumns() as $col)
+ {
+ if ($col->isForeignKey())
{
- if ($c->isForeignKey())
- {
- $method = 'get'.$c->getPhpName();
- $relatedTableName = $c->getRelatedTableName();
- $relatedColName = $c->getRelatedColumnName();
- $relatedPeerClass = ncClassFinder::getInstance()->findPeerClassName($relatedTableName);
- $relatedClass = ncClassFinder::getInstance()->findClassName($relatedTableName, $relatedPeerClass);
+ $method = 'get' . $col->getPhpName();
+ $relatedClass = $col->getRelatedTable()->getClassname();
- $criteria = new Criteria();
- $criteria->add(ncChangeLogEntryPeer::CLASS_NAME, $relatedClass);
- $criteria->add(ncChangeLogEntryPeer::OBJECT_PK, $object->$method());
-
- if (!is_null($from_date))
- $criteria->add(ncChangeLogEntryPeer::CREATED_AT, $from_date, Criteria::GREATER_THAN);
-
- $relatedChangeLog[$c->getName()] = ncChangeLogEntryPeer::doSelect($criteria);
- }
+ $relatedChangeLog[$col->getRelatedTable()->getPhpName()] = ncChangeLogEntryPeer::getChangeLogByPKandClassName($object->$method(), $relatedClass, $criteria, $transformToAdapters, $con);
}
}
- return $transformToAdapters ? self::getRelatedAdapters($relatedChangeLog) : $relatedChangeLog;
+ return $relatedChangeLog;
}
/**
* This methods inspects the columns of the object's table and if one of them if a foreign key,
* it returns the change log of the referenced object IF it points to the specified object (parameter).
+ *
+ * This method works only with Propel 1.5 or higher
*
* @param mixed $object
* @param date $from_date
@@ -192,81 +174,91 @@ public function get1NRelatedChangeLog(BaseObject $object, $from_date = null, $tr
*
* @return Array of ncChangeLogEntry
*/
- public function getNNRelatedChangeLog(BaseObject $object, $from_date = null, $transformToAdapters = true)
+ public function getNNRelatedChangeLog(BaseObject $object, $from_date = null, $transformToAdapters = true, PropelPDO $con = null)
{
- $relatedChangeLog = array();
- $relatedObjects = array();
-
- if (!is_null($object))
+ if (!defined("RelationMap::MANY_TO_MANY"))
{
- // Obtain object's information
- $object_class = get_class($object);
- $peer = constant($object_class.'::PEER');
+ throw new Exception("ncPropelChangeLogBehavior cannot handle M:M relationships unless you are using Propel 1.5 or higher");
+ }
+
+
+ /** @var ColumnMap */ $col;
+ /** @var TableMap */ $tableMap;
+ /** @var RelationMap*/ $rel;
- // Get all tableMaps and make the queries to retrieve all object instances that reference the object!!!
- ncClassFinder::getInstance()->reloadClasses();
+ $relatedChangeLog = array();
+ $criteria = new Criteria();
+
+ $class = get_class($object);
+ $peer = constant($class . '::PEER');
+ $tableMap = call_user_func(array($peer , 'getTableMap'));
- foreach (ncClassFinder::getInstance()->getPeerClasses() as $class => $path)
+
+ foreach ($tableMap->getRelations() as $rel)
+ {
+ // first we find our M:M relationship
+ if (RelationMap::MANY_TO_MANY == $rel->getType())
{
- if ($class != get_class($object) && class_exists($class) && method_exists($class, 'getTableMap'))
- {
- $criteria = new Criteria();
- $tableMap = call_user_func(array($class, 'getTableMap'));
+ $relatedTableMap = $rel->getLocalTable(); // yeah, it says local table... propel is strange like that ;)
+ $relatedTableObjectClass = $relatedTableMap->getClassname();
+ $relatedTablePeerClass = constant($relatedTableObjectClass . '::PEER');
+ $relatedTableName = $relatedTableMap->getPhpName();
- foreach ($tableMap->getColumns() as $c)
+ foreach ($tableMap->getRelations() as $relCrossRef)
+ {
+ // next we find the relationship that points to the CrossRef table
+ if (RelationMap::ONE_TO_MANY == $relCrossRef->getType() && false !== strpos($relCrossRef->getName(), $rel->getName()))
{
- if ($c->isForeignKey())
- {
- $method = 'get'.$c->getPhpName();
- $relatedTableName = $c->getRelatedTableName();
- $relatedColName = $c->getRelatedColumnName();
- $relatedPeerClass = ncClassFinder::getInstance()->findPeerClassName($relatedTableName);
- $relatedClass = ncClassFinder::getInstance()->findClassName($relatedTableName, $relatedPeerClass);
-
- // Traverse all collumns. If any has as its `relatedClass` the class of $object, make a
- // Criteria object to fetch every related object.
- if ($relatedClass == get_class($object))
+ /** @var TableMap */
+ $crossRefTableMap = $relCrossRef->getLocalTable();
+ $crossRefTableName = $crossRefTableMap->getName();
+ $crossRefObjectClass = $crossRefTableMap->getClassname();
+ $crossRefPeerClass = constant($crossRefObjectClass . '::PEER');
+
+ // For now, we won't handle composite relations... it's too much of a pain in the ass
+ if (!$relCrossRef->isComposite())
+ {
+ /** @var ColumnMap */
+ $crossRefColumnLocal = array_pop($relCrossRef->getLocalColumns());
+ /** @var ColumnMap */
+ $crossRefColumnForeign = array_pop($crossRefTableMap->getRelation($rel->getName())->getLocalColumns());
+ //$crossRefColumnForeign = array_pop($relCrossRef->getForeignColumns());
+
+ $criteria->clear();
+ $criteria->add($crossRefColumnLocal->getFullyQualifiedName(), ncChangeLogUtils::normalizePK($object));
+ $criteria->addSelectColumn($crossRefColumnForeign->getFullyQualifiedName());
+ $relatedTablePKs = call_user_func(array($crossRefPeerClass, 'doSelectStmt'), $criteria)->fetchAll(PDO::FETCH_COLUMN, 0);
+
+ $criteria->clear();
+ $criteria->add($crossRefColumnForeign->getRelatedName(), $relatedTablePKs, Criteria::IN);
+ $relatedObjects = call_user_func(array($relatedTablePeerClass, 'doSelect'), $criteria);
+
+ $criteria->clear();
+ if (!is_null($from_date))
{
- $criterion = $criteria->getNewCriterion(constant($class.'::'.$c->getName()), ncChangeLogUtils::normalizePK($object->getPrimaryKey()));
- $criteria->addOr($criterion);
+ $criteria->add(ncChangeLogEntryPeer::CREATED_AT, $from_date, Criteria::GREATER_THAN);
}
- }
- }
-
- if ($criteria->size() > 0)
- {
- $relatedObjects[$class] = call_user_func(array($class, 'doSelect'), $criteria);
- }
- }
- }
-
- // Get every object's change log
- foreach ($relatedObjects as $tableName => $objects)
- {
- foreach ($objects as $o)
- {
- $criteria = new Criteria();
-
- if (!is_null($from_date))
- {
- $criteria->add(ncChangeLogEntryPeer::CREATED_AT, $from_date, Criteria::GREATER_THAN);
- }
+
+ foreach ($relatedObjects as $relatedObject)
+ {
+ if (method_exists($relatedObject, '__toString'))
+ {
+ $changelogKey = $relatedObject->__toString();
+ }
+ else
+ {
+ $changelogKey = ncChangeLogUtils::normalizePK($relatedObject);
+ }
+
+ $relatedChangeLog[$relatedTableName][$changelogKey] = ncChangeLogEntryPeer::getChangeLogByPKandClassName($relatedObject->getPrimaryKey(), $relatedTableObjectClass, $criteria, $transformToAdapters, $con);;
+ }
+
+ } // if ($crossRefRel ! isComposite)
+ } // if ($crossRefRel is ONE_TO_MANY)
+ } // foreach ($relCrossRef)
+ } // if ($rel is MANY_TO_MANY)
+ } // foreach ($relations)
- if (sfMixer::getCallable('Base'.get_class($o).':getChangeLog') && count($changes = $o->getChangeLog($criteria)) > 0)
- {
- if (method_exists($o, '__toString'))
- {
- $relatedChangeLog[$tableName][strval($o)] = $changes;
- }
- else
- {
- $relatedChangeLog[$tableName][ncChangeLogUtils::normalizePK($o->getPrimaryKey())] = $changes;
- }
- }
- }
- }
- }
-
return $relatedChangeLog;
}
@@ -279,7 +271,7 @@ public function getNNRelatedChangeLog(BaseObject $object, $from_date = null, $tr
*/
public function getChangeLogRoute(BaseObject $object)
{
- return '@nc_change_log?class='.get_class($object).'&pk='.ncChangeLogUtils::normalizePK($object->getPrimaryKey());
+ return '@nc_change_log?class='.get_class($object).'&pk='.ncChangeLogUtils::normalizePK($object);
}
@@ -324,7 +316,7 @@ protected static function _update_changes(BaseObject $object)
'field' => $col_fieldName,
'raw' => array(
// the previous version used toArray for these values, but this is exactly the same
- 'old' => $stored_values->$value_method(),
+ 'old' => $stored_object->$value_method(),
'new' => $object->$value_method(),
)
);
View
6 lib/util/ncChangeLogUtils.class.php
@@ -81,12 +81,18 @@ static public function extractValueMethod(ColumnMap $column)
* 123 => "123"
* array(123) => "123"
* array(123, 456) => "123-456"
+ * BaseObject $o => PK
*
* @param mixed $primary_key
* @return string
*/
public static function normalizePK($primary_key)
{
+ if ($primary_key instanceof BaseObject)
+ {
+ $primary_key = $primary_key->getPrimaryKey();
+ }
+
return is_array($primary_key) ? (count($primary_key) > 1 ? implode('-', $primary_key) : array_pop($primary_key)) : $primary_key;
}
View
127 lib/util/ncClassFinder.class.php
@@ -1,127 +0,0 @@
-<?php
-
-class ncClassFinder
-{
- static protected
- $freshCache = false,
- $instance = null;
-
- protected
- $overriden = array(),
- $classes = array();
-
- protected function __construct()
- {
- }
-
- static public function getInstance()
- {
- if (!isset(self::$instance))
- {
- self::$instance = new ncClassFinder();
- }
-
- return self::$instance;
- }
-
- public function getPeerClasses()
- {
- return $this->classes;
- }
-
- public function setClassPath($class, $path)
- {
- $this->overriden[$class] = $path;
-
- $this->classes[$class] = $path;
- }
-
- public function getClassPath($class)
- {
- return isset($this->classes[$class]) ? $this->classes[$class] : null;
- }
-
- public function reloadClasses($force = false)
- {
- // only (re)load the autoloading cache once per request
- if (self::$freshCache)
- {
- return;
- }
-
- $configuration = sfProjectConfiguration::getActive();
- if (!$configuration || !$configuration instanceof sfApplicationConfiguration)
- {
- return;
- }
-
- self::$freshCache = true;
- if (file_exists($configuration->getConfigCache()->getCacheName('config/autoload.yml')))
- {
- self::$freshCache = false;
- if ($force)
- {
- unlink($configuration->getConfigCache()->getCacheName('config/autoload.yml'));
- }
- }
-
- $file = $configuration->getConfigCache()->checkConfig('config/autoload.yml');
-
- $this->classes = include($file);
-
- //If the user has specified provided one or more class paths
- foreach ($this->overriden as $class => $path)
- {
- $this->classes[$class] = $path;
- }
-
- //Remove non Peer classes from the array.
- foreach ($this->classes as $className => $path)
- {
- if ((substr($className, -4, 4) != 'Peer')
- || ((substr($className, -4, 4) == 'Peer') && (substr($className, 0, 4) == 'Base')))
- {
- unset($this->classes[$className]);
- }
- }
- }
-
- public function findClassName($tableName, $peerClass = null, $absolute = false)
- {
- $peerClass = is_null($peerClass)? $this->findPeerClassName($tableName) : $peerClass;
- if (!is_null($peerClass))
- {
- if (method_exists($peerClass, 'getOMClass'))
- {
- $className = explode(".", call_user_func(array($peerClass, 'getOMClass')));
- return is_array($className) && count($className) > 0? $className[count($className)-1] : null;
- }
- }
- return null;
- }
-
- public function findPeerClassName($tableName)
- {
- if (!$this->classes)
- {
- $this->reloadClasses();
- }
-
- foreach ($this->classes as $key => $class)
- {
- $tmp = explode(DIRECTORY_SEPARATOR, $key);
- $className = (is_array($tmp) && (count($tmp) > 0))
- ? $tmp[count($tmp)-1]
- : null;
- if (!is_null($className) && defined($className.'::TABLE_NAME'))
- {
- $classTableName = constant($className.'::TABLE_NAME');
- if (!is_null($classTableName) && $classTableName == $tableName)
- {
- return $className;
- }
- }
- }
- return null;
- }
-}
View
12 test/functional/fixtures/config/propel.ini
@@ -1,4 +1,4 @@
- propel.targetPackage = lib.model
+propel.targetPackage = lib.model
propel.packageObjectModel = true
propel.project = project
propel.database = sqlite
@@ -48,8 +48,8 @@ propel.builder.addBehaviors = true
; behaviors
propel.behavior.default = symfony,symfony_i18n
-propel.behavior.symfony.class = plugins.sfPropelPlugin.lib.behavior.SfPropelBehaviorSymfony
-propel.behavior.symfony_i18n.class = plugins.sfPropelPlugin.lib.behavior.SfPropelBehaviorI18n
-propel.behavior.symfony_i18n_translation.class = plugins.sfPropelPlugin.lib.behavior.SfPropelBehaviorI18nTranslation
-propel.behavior.symfony_behaviors.class = plugins.sfPropelPlugin.lib.behavior.SfPropelBehaviorSymfonyBehaviors
-propel.behavior.symfony_timestampable.class = plugins.sfPropelPlugin.lib.behavior.SfPropelBehaviorTimestampable
+propel.behavior.symfony.class = plugins.sfPropel15Plugin.lib.behavior.SfPropelBehaviorSymfony
+propel.behavior.symfony_i18n.class = plugins.sfPropel15Plugin.lib.behavior.SfPropelBehaviorI18n
+propel.behavior.symfony_i18n_translation.class = plugins.sfPropel15Plugin.lib.behavior.SfPropelBehaviorI18nTranslation
+propel.behavior.symfony_behaviors.class = plugins.sfPropel15Plugin.lib.behavior.SfPropelBehaviorSymfonyBehaviors
+propel.behavior.symfony_timestampable.class = plugins.sfPropel15Plugin.lib.behavior.SfPropelBehaviorTimestampable
View
2  test/functional/fixtures/config/schema.xml
@@ -45,7 +45,7 @@
<column name="name" type="varchar" size="255" />
</table>
- <table name="author_article">
+ <table name="author_article" isCrossRef="true">
<behavior name="symfony">
<parameter name="form" value="false"/>
<parameter name="filter" value="false"/>
View
2  test/functional/fixtures/lib/model/Article.php
@@ -19,3 +19,5 @@
class Article extends BaseArticle {
} // Article
+
+sfPropelBehavior::add('Article', array('changelog'));
View
2  test/functional/fixtures/lib/model/Author.php
@@ -19,3 +19,5 @@
class Author extends BaseAuthor {
} // Author
+
+sfPropelBehavior::add('Author', array('changelog'));
View
2  test/functional/fixtures/lib/model/Category.php
@@ -19,3 +19,5 @@
class Category extends BaseCategory {
} // Category
+
+sfPropelBehavior::add('Category', array('changelog'));
View
30 test/unit/behavior/ncPropelChangeLogBehaviorTest.php
@@ -0,0 +1,30 @@
+<?php
+
+$fixtures = 'fixtures/fixtures.yml';
+
+require_once(dirname(__FILE__).'/../../bootstrap/functional.php');
+
+$t = new lime_test();
+$t->diag('Testing lib/behavior/ncPropelChangeLogBehavior.class.php');
+
+try{
+
+$book = BookPeer::doSelectOne(new Criteria());
+
+$book->setName("The hitchhiker's guide to the galaxy");
+$book->save();
+
+$book->getChangeLog();
+
+$article = ArticlePeer::doSelectOne(new Criteria());
+
+
+
+$article->get1NRelatedChangeLog();
+
+$article->getNNRelatedChangeLog();
+
+ $t->pass('No exceptions... maybe everything is fine?');
+} catch (Exception $e) {
+ $t->fail('Failed with exception :'.$e->getMessage());
+}
Please sign in to comment.
Something went wrong with that request. Please try again.