From 25260755021d53ae32a184f851fa920cb7d1205d Mon Sep 17 00:00:00 2001 From: Jason Coward Date: Fri, 6 Sep 2013 17:01:24 -0600 Subject: [PATCH] [#10183] Fix cache entry removal on xPDOObject::remove() --- test/xPDO/xPDOCache/xPDOCacheDb.php | 163 +++++++++++++++++++++ test/xPDO/xPDOCache/xPDOCache_AllTests.php | 4 +- xpdo/changelog.txt | 2 + xpdo/om/xpdoobject.class.php | 18 ++- xpdo/xpdo.class.php | 4 +- 5 files changed, 186 insertions(+), 5 deletions(-) create mode 100644 test/xPDO/xPDOCache/xPDOCacheDb.php diff --git a/test/xPDO/xPDOCache/xPDOCacheDb.php b/test/xPDO/xPDOCache/xPDOCacheDb.php new file mode 100644 index 00000000..b433f461 --- /dev/null +++ b/test/xPDO/xPDOCache/xPDOCacheDb.php @@ -0,0 +1,163 @@ +xpdo->getManager(); + + $this->xpdo->manager->createObjectContainer('Phone'); + $this->xpdo->manager->createObjectContainer('Person'); + $this->xpdo->manager->createObjectContainer('PersonPhone'); + $this->xpdo->manager->createObjectContainer('BloodType'); + + $bloodTypes = array('A+','A-','B+','B-','AB+','AB-','O+','O-'); + foreach ($bloodTypes as $bloodType) { + $bt = $this->xpdo->newObject('BloodType'); + $bt->set('type',$bloodType); + $bt->set('description',''); + if (!$bt->save()) { + $this->xpdo->log(xPDO::LOG_LEVEL_FATAL,'Could not add blood type: '.$bloodType); + } + } + + $bloodTypeABPlus = $this->xpdo->getObject('BloodType','AB+'); + if (empty($bloodTypeABPlus)) $this->xpdo->log(xPDO::LOG_LEVEL_FATAL,'Could not load blood type.'); + + /* add some people */ + $person= $this->xpdo->newObject('Person'); + $person->set('first_name', 'Johnathon'); + $person->set('last_name', 'Doe'); + $person->set('middle_name', 'Harry'); + $person->set('dob', '1950-03-14'); + $person->set('gender', 'M'); + $person->set('password', 'ohb0ybuddy'); + $person->set('username', 'john.doe@gmail.com'); + $person->set('security_level', 3); + $person->set('blood_type',$bloodTypeABPlus->get('type')); + $person->save(); + + $phone = $this->xpdo->newObject('Phone'); + $phone->fromArray(array( + 'type' => 'work', + 'number' => '555-111-1111', + )); + $phone->save(); + + $personPhone = $this->xpdo->newObject('PersonPhone'); + $personPhone->fromArray(array( + 'person' => 1, + 'phone' => 1, + 'is_primary' => true, + ),'',true,true); + $personPhone->save(); + + $person= $this->xpdo->newObject('Person'); + $person->set('first_name', 'Jane'); + $person->set('last_name', 'Heartstead'); + $person->set('middle_name', 'Cecilia'); + $person->set('dob', '1978-10-23'); + $person->set('gender', 'F'); + $person->set('password', 'n0w4yimdoingthat'); + $person->set('username', 'jane.heartstead@yahoo.com'); + $person->set('security_level',1); + $person->set('blood_type',$bloodTypeABPlus->get('type')); + $person->save(); + + $phone = $this->xpdo->newObject('Phone'); + $phone->fromArray(array( + 'type' => 'work', + 'number' => '555-222-2222', + )); + $phone->save(); + + $personPhone = $this->xpdo->newObject('PersonPhone'); + $personPhone->fromArray(array( + 'person' => 2, + 'phone' => 2, + 'is_primary' => true, + ),'',true,true); + $personPhone->save(); + + $phone = $this->xpdo->newObject('Phone'); + $phone->fromArray(array( + 'type' => 'home', + 'number' => '555-555-5555', + )); + $phone->save(); + + $personPhone = $this->xpdo->newObject('PersonPhone'); + $personPhone->fromArray(array( + 'person' => 2, + 'phone' => 3, + 'is_primary' => false, + ),'',true,true); + $personPhone->save(); + } catch (Exception $e) { + $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, $e->getMessage(), '', __METHOD__, __FILE__, __LINE__); + } + } + + /** + * Remove dummy data prior to each test. + */ + public function tearDown() { + try { + $this->xpdo->manager->removeObjectContainer('Phone'); + $this->xpdo->manager->removeObjectContainer('Person'); + $this->xpdo->manager->removeObjectContainer('PersonPhone'); + $this->xpdo->manager->removeObjectContainer('BloodType'); + } catch (Exception $e) { + $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, $e->getMessage(), '', __METHOD__, __FILE__, __LINE__); + } + parent::tearDown(); + } + + /** + * Ensure cache entries for class do not remain when removing an object. + */ + public function testRemoveObject() { + $this->xpdo->setOption(xPDO::OPT_CACHE_DB, true); + + $people= $this->xpdo->getCollection('Person'); + + /** @var Person $person */ + $person= $this->xpdo->getObject('Person', 1); + $person->remove(); + + $people= $this->xpdo->getCollection('Person'); + $count= count($people); + + $this->assertEquals(0, $this->xpdo->getCount('Person', 1), "Object still exists after remove"); + $this->assertEquals(1, $count, "Object still exists in cache after removal"); + } +} diff --git a/test/xPDO/xPDOCache/xPDOCache_AllTests.php b/test/xPDO/xPDOCache/xPDOCache_AllTests.php index 585cf726..1a173d30 100644 --- a/test/xPDO/xPDOCache/xPDOCache_AllTests.php +++ b/test/xPDO/xPDOCache/xPDOCache_AllTests.php @@ -20,6 +20,7 @@ * @package xpdo-test */ require_once 'xPDOCacheManager.php'; +require_once 'xPDOCacheDb.php'; /** * Suite handling all xPDOCache related tests. * @@ -30,6 +31,7 @@ class xPDOCache_AllTests extends PHPUnit_Framework_TestSuite { public static function suite() { $suite = new xPDOCache_AllTests('xPDOCacheTest'); $suite->addTestSuite('xPDOCacheManagerTest'); + $suite->addTestSuite('xPDOCacheDbTest'); return $suite; } -} \ No newline at end of file +} diff --git a/xpdo/changelog.txt b/xpdo/changelog.txt index 4fff5c05..c53ee1b5 100644 --- a/xpdo/changelog.txt +++ b/xpdo/changelog.txt @@ -1,5 +1,7 @@ This file shows the changes in this release of xPDO. +- [#10183] Fix cache entry removal on xPDOObject::remove() + xPDO 2.2.8-pl (August 26, 2013) ==================================== - [#9864] Identify compound PK's properly in xPDOQuery::parseConditions() diff --git a/xpdo/om/xpdoobject.class.php b/xpdo/om/xpdoobject.class.php index 6a890e53..7818b61f 100644 --- a/xpdo/om/xpdoobject.class.php +++ b/xpdo/om/xpdoobject.class.php @@ -1642,9 +1642,21 @@ public function remove(array $ancestors= array ()) { if ($callback && is_callable($callback)) { call_user_func($callback, array('className' => $this->_class, 'criteria' => $delete, 'object' => $this)); } - if ($this->xpdo->_cacheEnabled) { - $cacheKey= is_array($pk) ? implode('_', $pk) : $pk; - $this->xpdo->toCache($this->xpdo->getTableClass($this->_class) . '_' . $cacheKey, null, 0, array('modified' => true)); + if ($this->xpdo->_cacheEnabled && $this->xpdo->getOption('cache_db', null, false)) { + /** @var xPDOCache $dbCache */ + $dbCache = $this->xpdo->getCacheManager()->getCacheProvider( + $this->getOption('cache_db_key', null, 'db'), + array( + xPDO::OPT_CACHE_KEY => $this->getOption('cache_db_key', null, 'db'), + xPDO::OPT_CACHE_HANDLER => $this->getOption(xPDO::OPT_CACHE_DB_HANDLER, null, $this->getOption(xPDO::OPT_CACHE_HANDLER, null, 'cache.xPDOFileCache')), + xPDO::OPT_CACHE_FORMAT => (integer) $this->getOption('cache_db_format', null, $this->getOption(xPDO::OPT_CACHE_FORMAT, null, xPDOCacheManager::CACHE_PHP)), + xPDO::OPT_CACHE_EXPIRES => (integer) $this->getOption(xPDO::OPT_CACHE_DB_EXPIRES, null, $this->getOption(xPDO::OPT_CACHE_EXPIRES, null, 0)), + xPDO::OPT_CACHE_PREFIX => $this->getOption('cache_db_prefix', null, xPDOCacheManager::CACHE_DIR) + ) + ); + if (!$dbCache->delete($this->_class, array('multiple_object_delete' => true))) { + $this->xpdo->log(xPDO::LOG_LEVEL_WARN, "Could not remove cache entries for {$this->_class}", '', __METHOD__, __FILE__, __LINE__); + } } $this->xpdo->log(xPDO::LOG_LEVEL_INFO, "Removed {$this->_class} instance with primary key " . print_r($pk, true)); } diff --git a/xpdo/xpdo.class.php b/xpdo/xpdo.class.php index 977895b2..a0e0babb 100644 --- a/xpdo/xpdo.class.php +++ b/xpdo/xpdo.class.php @@ -2303,6 +2303,7 @@ public function toCache($signature, $object, $lifetime= 0, $options = array()) { xPDO::OPT_CACHE_KEY => $this->getOption('cache_db_key', $options, 'db'), xPDO::OPT_CACHE_HANDLER => $this->getOption(xPDO::OPT_CACHE_DB_HANDLER, $options, $this->getOption(xPDO::OPT_CACHE_HANDLER, $options, 'cache.xPDOFileCache')), xPDO::OPT_CACHE_FORMAT => (integer) $this->getOption('cache_db_format', $options, $this->getOption(xPDO::OPT_CACHE_FORMAT, $options, xPDOCacheManager::CACHE_PHP)), + xPDO::OPT_CACHE_EXPIRES => (integer) $this->getOption(xPDO::OPT_CACHE_DB_EXPIRES, null, $this->getOption(xPDO::OPT_CACHE_EXPIRES, null, 0)), xPDO::OPT_CACHE_PREFIX => $this->getOption('cache_db_prefix', $options, xPDOCacheManager::CACHE_DIR), 'multiple_object_delete' => true ))); @@ -2316,7 +2317,8 @@ public function toCache($signature, $object, $lifetime= 0, $options = array()) { xPDO::OPT_CACHE_KEY => $this->getOption('cache_db_key', $options, 'db'), xPDO::OPT_CACHE_HANDLER => $this->getOption(xPDO::OPT_CACHE_DB_HANDLER, $options, $this->getOption(xPDO::OPT_CACHE_HANDLER, $options, 'cache.xPDOFileCache')), xPDO::OPT_CACHE_FORMAT => (integer) $this->getOption('cache_db_format', $options, $this->getOption(xPDO::OPT_CACHE_FORMAT, $options, xPDOCacheManager::CACHE_PHP)), - 'cache_prefix' => $this->getOption('cache_db_prefix', $options, xPDOCacheManager::CACHE_DIR) + xPDO::OPT_CACHE_EXPIRES => (integer) $this->getOption(xPDO::OPT_CACHE_DB_EXPIRES, null, $this->getOption(xPDO::OPT_CACHE_EXPIRES, null, 0)), + xPDO::OPT_CACHE_PREFIX => $this->getOption('cache_db_prefix', $options, xPDOCacheManager::CACHE_DIR) )); $result= $this->cacheManager->set($sig, $object, $lifetime, $cacheOptions); if ($result && $object instanceof xPDOObject) {