/** * Remove the persistent instance of an object permanently. * * Deletes the persistent object isntance stored in the database when * called, including any dependent objects defined by composite foreign key * relationships. * * @todo Implement some way to reassign ownership of related composite * objects when remove is called, perhaps by passing another object * instance as an optional parameter, or creating a separate method. * * @param array $ancestors Keeps track of classes which have already been * removed to prevent loop with circular references. * @return boolean Returns true on success, false on failure. */ public function remove(array $ancestors = array()) { $result = false; $pk = $this->getPrimaryKey(); if ($pk && $this->xpdo->getConnection(array(xPDO::OPT_CONN_MUTABLE => true))) { if (!empty($this->_composites)) { $current = array($this->_class, $this->_alias); foreach ($this->_composites as $compositeAlias => $composite) { if (in_array($compositeAlias, $ancestors) || in_array($composite['class'], $ancestors)) { continue; } if ($composite['cardinality'] === 'many') { if ($many = $this->getMany($compositeAlias)) { foreach ($many as $one) { $ancestors[] = $compositeAlias; $newAncestors = $ancestors + $current; if (!$one->remove($newAncestors)) { $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Error removing dependent object: " . print_r($one->toArray('', true), true)); } } unset($many); } } elseif ($one = $this->getOne($compositeAlias)) { $ancestors[] = $compositeAlias; $newAncestors = $ancestors + $current; if (!$one->remove($newAncestors)) { $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Error removing dependent object: " . print_r($one->toArray('', true), true)); } unset($one); } } } $delete = $this->xpdo->newQuery($this->_class); $delete->command('DELETE'); $delete->where($pk); // $delete->limit(1); $stmt = $delete->prepare(); if (is_object($stmt)) { if (!($result = $stmt->execute())) { $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'Could not delete from ' . $this->_table . '; primary key specified was ' . print_r($pk, true) . "\n" . print_r($stmt->errorInfo(), true)); } else { $callback = $this->getOption(xPDO::OPT_CALLBACK_ON_REMOVE); 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)); } $this->xpdo->log(xPDO::LOG_LEVEL_INFO, "Removed {$this->_class} instance with primary key " . print_r($pk, true)); } } else { $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'Could not build criteria to delete from ' . $this->_table . '; primary key specified was ' . print_r($pk, true)); } } return $result; }
/** * Remove the persistent instance of an object permanently. * * Deletes the persistent object instance stored in the database when * called, including any dependent objects defined by composite foreign key * relationships. * * @todo Implement some way to reassign ownership of related composite * objects when remove is called, perhaps by passing another object * instance as an optional parameter, or creating a separate method. * * @param array $ancestors Keeps track of classes which have already been * removed to prevent loop with circular references. * @return boolean Returns true on success, false on failure. */ public function remove(array $ancestors = array()) { $result = false; $pk = $this->getPrimaryKey(); if ($pk && $this->xpdo->getConnection(array(xPDO::OPT_CONN_MUTABLE => true))) { if (!empty($this->_composites)) { $current = array($this->_class, $this->_alias); foreach ($this->_composites as $compositeAlias => $composite) { if (in_array($compositeAlias, $ancestors) || in_array($composite['class'], $ancestors)) { continue; } if ($composite['cardinality'] === 'many') { if ($many = $this->getMany($compositeAlias)) { /** @var xPDOObject $one */ foreach ($many as $one) { $ancestors[] = $compositeAlias; $newAncestors = $ancestors + $current; if (!$one->remove($newAncestors)) { $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Error removing dependent object: " . print_r($one->toArray('', true), true)); } } unset($many); } } elseif ($one = $this->getOne($compositeAlias)) { $ancestors[] = $compositeAlias; $newAncestors = $ancestors + $current; if (!$one->remove($newAncestors)) { $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Error removing dependent object: " . print_r($one->toArray('', true), true)); } unset($one); } } } $delete = $this->xpdo->newQuery($this->_class); $delete->command('DELETE'); $delete->where($pk); // $delete->limit(1); $stmt = $delete->prepare(); if (is_object($stmt)) { $tstart = microtime(true); if (!($result = $stmt->execute())) { $this->xpdo->queryTime += microtime(true) - $tstart; $this->xpdo->executedQueries++; $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'Could not delete from ' . $this->_table . '; primary key specified was ' . print_r($pk, true) . "\n" . print_r($stmt->errorInfo(), true)); } else { $this->xpdo->queryTime += microtime(true) - $tstart; $this->xpdo->executedQueries++; $callback = $this->getOption(xPDO::OPT_CALLBACK_ON_REMOVE); if ($callback && is_callable($callback)) { call_user_func($callback, array('className' => $this->_class, 'criteria' => $delete, 'object' => $this)); } 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 => (int) $this->getOption('cache_db_format', null, $this->getOption(xPDO::OPT_CACHE_FORMAT, null, xPDOCacheManager::CACHE_PHP)), xPDO::OPT_CACHE_EXPIRES => (int) $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)); } } else { $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'Could not build criteria to delete from ' . $this->_table . '; primary key specified was ' . print_r($pk, true)); } } return $result; }