Created
February 7, 2011 12:58
-
-
Save stephaneerard/814320 to your computer and use it in GitHub Desktop.
Fixing pdo queries with table connection parameter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| class dmPageSynchronizer | |
| { | |
| protected | |
| $moduleManager, | |
| $nodeParentIdStmt; | |
| public function __construct(dmModuleManager $moduleManager) | |
| { | |
| $this->moduleManager = $moduleManager; | |
| } | |
| public function execute(array $onlyModules = array()) | |
| { | |
| if(empty($onlyModules)) | |
| { | |
| $onlyModules = $this->moduleManager->getProjectModules(); | |
| } | |
| elseif(is_string(dmArray::first($onlyModules))) | |
| { | |
| $onlyModules = $this->moduleManager->keysToModules($onlyModules); | |
| } | |
| $onlyModules = dmModuleManager::removeModulesChildren($onlyModules); | |
| $this->updateListPages(); | |
| $this->removeShowPages($onlyModules); | |
| $this->updateShowPages($onlyModules); | |
| } | |
| protected function removeShowPages(array $onlyModules) | |
| { | |
| $modulesToCheck = dmDb::pdo('SELECT DISTINCT p.module FROM dm_page p WHERE p.action = ?', array('show'), dmDb::table('DmPage')->getConnection())->fetchAll(PDO::FETCH_COLUMN); | |
| foreach($onlyModules as $moduleKey => $module) | |
| { | |
| $this->removeModuleShowPagesRecursive($module, $modulesToCheck); | |
| } | |
| } | |
| protected function removeModuleShowPagesRecursive(dmModule $module, array $modulesToCheck) | |
| { | |
| $moduleKey = $module->getKey(); | |
| if (!in_array($moduleKey, $modulesToCheck) || !$module->hasPage()) | |
| { | |
| foreach($module->getChildren() as $child) | |
| { | |
| $this->removeModuleShowPagesRecursive($child, $modulesToCheck); | |
| } | |
| return; | |
| } | |
| $showPages = dmDb::pdo('SELECT p.id, p.module, p.record_id FROM dm_page p WHERE p.module = ? AND p.action = ?', array($moduleKey, 'show'), dmDb::table('DmPage')->getConnection())->fetchAll(PDO::FETCH_ASSOC); | |
| $showPageRecordIds = array(); | |
| foreach($showPages as $showPage) | |
| { | |
| $showPageRecordIds[] = $showPage['record_id']; | |
| } | |
| if ($module->hasListPage()) | |
| { | |
| if (!empty($showPageRecordIds)) | |
| { | |
| $query = sprintf('SELECT r.id FROM %s r WHERE r.id IN (%s)', | |
| $module->getTable()->getTableName(), | |
| implode(',', $showPageRecordIds) | |
| ); | |
| $records = array_flip(dmDb::pdo($query, array(), $module->getTable()->getConnection())->fetchAll(PDO::FETCH_COLUMN)); | |
| } | |
| else | |
| { | |
| $records = array(); | |
| } | |
| $parentModule = $module; | |
| $parentRecordIds = false; | |
| } | |
| else | |
| { | |
| $select = 'r.id'; | |
| if ($module->hasLocal($module->getParent())) | |
| { | |
| $select .= ', r.'.$module->getTable()->getRelationHolder()->getLocalByClass($module->getParent()->getModel())->getLocal(); | |
| } | |
| if (!empty($showPageRecordIds)) | |
| { | |
| $query = sprintf('SELECT %s FROM %s r WHERE r.id IN (%s)', | |
| $select, | |
| $module->getTable()->getTableName(), | |
| implode(',', $showPageRecordIds) | |
| ); | |
| $_records = dmDb::pdo($query, array(), $module->getTable()->getConnection())->fetchAll(PDO::FETCH_ASSOC); | |
| $records = array(); | |
| foreach($_records as $_record) | |
| { | |
| $records[$_record['id']] = $_record; | |
| } | |
| } | |
| else | |
| { | |
| $records = array(); | |
| } | |
| $parentModule = $module->getNearestAncestorWithPage(); | |
| $parentRecordIds = $this->getParentRecordIds($module, $parentModule); | |
| } | |
| foreach($showPages as $showPage) | |
| { | |
| $pageIsUseless = false; | |
| if(!isset($records[$showPage['record_id']])) | |
| { | |
| $pageIsUseless = true; | |
| } | |
| elseif(!$module->hasListPage()) // parent page is a show page | |
| { | |
| $record = $records[$showPage['record_id']]; | |
| /* | |
| * If the parent is a show page, verify that it exists, | |
| * unless the child page is useless | |
| */ | |
| if ($parentRecordIds !== false) | |
| { | |
| $parentRecordId = isset($parentRecordIds[$record['id']]) ? $parentRecordIds[$record['id']] : null; | |
| } | |
| else | |
| { | |
| $parentRecordId = dmDb::create($module->getModel(), $record)->getAncestorRecordId($parentModule->getModel()); | |
| } | |
| if (!$parentRecordId) | |
| { | |
| $pageIsUseless = true; | |
| } | |
| } | |
| if ($pageIsUseless) | |
| { | |
| //delete node only if it's found | |
| if( ($page = dmDb::table('DmPage')->find($showPage['id']) ) ) | |
| { | |
| $page->getNode()->delete(); | |
| } | |
| } | |
| } | |
| foreach($module->getChildren() as $child) | |
| { | |
| $this->removeModuleShowPagesRecursive($child, $modulesToCheck); | |
| } | |
| } | |
| protected function updateListPages() | |
| { | |
| $projectModules = $this->moduleManager->getProjectModules(); | |
| foreach($projectModules as $key => $module) | |
| { | |
| if(!$module->hasListPage()) | |
| { | |
| unset($projectModules[$key]); | |
| } | |
| } | |
| $projectModuleKeys = array_keys($projectModules); | |
| $_listPages = dmDb::pdo('SELECT p.id, p.module FROM dm_page p WHERE p.action = ?', array('list'), dmDb::table('DmPage')->getConnection())->fetchAll(PDO::FETCH_ASSOC); | |
| $listPages = array(); | |
| foreach($_listPages as $_listPage) | |
| { | |
| $listPages[$_listPage['module']] = $_listPage['id']; | |
| } | |
| foreach($projectModules as $moduleKey => $module) | |
| { | |
| /* | |
| * Only root modules, which have no parent, need a list page | |
| */ | |
| if (!isset($listPages[$moduleKey])) | |
| { | |
| if (isset($listPages[strtolower($moduleKey)])) | |
| { | |
| // fix page module | |
| dmDb::table('DmPage')->createQuery() | |
| ->update('DmPage') | |
| ->where('id = ?', $listPages[strtolower($moduleKey)]) | |
| ->set('module', "'".$moduleKey."'") | |
| ->execute(); | |
| } | |
| else | |
| { | |
| // create page | |
| dmDb::create('DmPage', array( | |
| 'module' => $moduleKey, | |
| 'action' => 'list', | |
| 'name' => $module->getPlural(), | |
| 'title' => $module->getPlural(), | |
| 'slug' => dmString::slugify($module->getPlural()), | |
| 'description' => $module->getPlural() | |
| ))->getNode()->insertAsLastChildOf(dmDb::table('DmPage')->getTree()->fetchRoot()); | |
| } | |
| } | |
| } | |
| } | |
| protected function updateShowPages(array $onlyModules) | |
| { | |
| foreach($onlyModules as $moduleKey => $module) | |
| { | |
| $this->updateModuleShowPagesRecursive($module); | |
| } | |
| } | |
| protected function updateModuleShowPagesRecursive(dmModule $module) | |
| { | |
| $moduleKey = $module->getKey(); | |
| if (!$module->hasPage()) | |
| { | |
| foreach($module->getChildren() as $child) | |
| { | |
| $this->updateModuleShowPagesRecursive($child); | |
| } | |
| return; | |
| } | |
| /* | |
| * prepares pages to update | |
| */ | |
| $_showPages = dmDb::pdo('SELECT p.id, p.module, p.record_id, p.lft, p.rgt FROM dm_page p WHERE p.module = ? AND p.action = ?', array( | |
| $moduleKey, 'show' | |
| ), dmDb::table('DmPage')->getConnection())->fetchAll(PDO::FETCH_ASSOC); | |
| $showPages = array(); | |
| foreach($_showPages as $_showPage) | |
| { | |
| $showPages[$_showPage['record_id']] = $_showPage; | |
| } | |
| if ($module->hasListPage()) | |
| { | |
| $parentModule = $module; | |
| /* | |
| * prepare records | |
| */ | |
| // http://github.com/diem-project/diem/issues#issue/182 | |
| if(count($module->getTable()->getOption('inheritanceMap'))) | |
| { | |
| $records = $module->getTable()->createQuery('r')->select('r.id')->fetchArray(); | |
| } | |
| else | |
| { | |
| $records = dmDb::pdo('SELECT r.id FROM '.$module->getTable()->getTableName().' r', array(), $module->getTable()->getConnection())->fetchAll(PDO::FETCH_ASSOC); | |
| } | |
| /* | |
| * prepare parent pages | |
| */ | |
| $parentPageIds = dmDb::pdo('SELECT p.id FROM dm_page p WHERE p.module = ? AND p.action = ?', array($moduleKey, 'list'), dmDb::table('DmPage')->getConnection())->fetch(PDO::FETCH_NUM); | |
| $parentPageIds = $parentPageIds[0]; | |
| if (!$parentPageIds) | |
| { | |
| throw new dmException(sprintf('%s needs a parent page, %s.%s, but it does not exists', $module, $moduleKey, 'list')); | |
| } | |
| $parentRecordIds = false; | |
| } | |
| else | |
| { | |
| if (!$parentModule = $module->getNearestAncestorWithPage()) | |
| { | |
| throw new dmException(sprintf( | |
| '%s module is child of %s module, but %s module has no ancestor with page', | |
| $module, $parentModule, $module | |
| )); | |
| } | |
| /* | |
| * prepare records | |
| */ | |
| $select = 'r.id'; | |
| if ($module->hasLocal($module->getParent())) | |
| { | |
| $select .= ', r.'.$module->getTable()->getRelationHolder()->getLocalByClass($module->getParent()->getModel())->getLocal(); | |
| } | |
| // http://github.com/diem-project/diem/issues#issue/182 | |
| if(count($module->getTable()->getOption('inheritanceMap'))) | |
| { | |
| $records = $module->getTable()->createQuery('r')->select($select)->fetchArray(); | |
| } | |
| else | |
| { | |
| $records = dmDb::pdo('SELECT '.$select.' FROM '.$module->getTable()->getTableName().' r', array(), $module->getTable()->getConnection())->fetchAll(PDO::FETCH_ASSOC); | |
| } | |
| /* | |
| * prepare parent pages | |
| */ | |
| $_parentPageIds = dmDb::pdo('SELECT p.id, p.record_id FROM dm_page p WHERE p.module = ? AND p.action = ?', array($parentModule->getKey(), 'show'), dmDb::table('DmPage')->getConnection())->fetchAll(PDO::FETCH_NUM); | |
| $parentPageIds = array(); | |
| foreach($_parentPageIds as $value) $parentPageIds[$value[1]] = $value[0]; | |
| $parentRecordIds = $this->getParentRecordIds($module, $parentModule); | |
| } | |
| foreach($records as $record) | |
| { | |
| if (isset($showPages[$record['id']])) | |
| { | |
| $page = $showPages[$record['id']]; | |
| } | |
| else | |
| { | |
| $page = array( | |
| 'id' => null, | |
| 'record_id' => $record['id'], | |
| 'module' => $moduleKey, | |
| 'action' => 'show' | |
| ); | |
| } | |
| try | |
| { | |
| $this->updatePageFromRecord($page, $record, $module, $parentModule, $parentPageIds, $parentRecordIds); | |
| } | |
| catch(dmPageMustNotExistException $e) | |
| { | |
| if ($page['id']) | |
| { | |
| dmDb::table('DmPage')->find($page['id'])->getNode()->delete(); | |
| } | |
| } | |
| } | |
| foreach($module->getChildren() as $child) | |
| { | |
| $this->updateModuleShowPagesRecursive($child); | |
| } | |
| } | |
| public function updatePageFromRecord(array $page, array $record, dmProjectModule $module, dmProjectModule $parentModule, $parentPageIds, $parentRecordIds) | |
| { | |
| $moduleKey = $module->getKey(); | |
| $recordTable = $module->getTable(); | |
| $pageTable = dmDb::table('DmPage'); | |
| //@todo make this behavior optional to not break BC ? | |
| if($recordTable->isNestedSet()) | |
| { | |
| $recordObj = $recordTable->findOneBy($recordTable->getIdentifier(), $record['id']); | |
| $recordNode = $recordObj->getNode(); | |
| if($recordNode->isRoot()) | |
| { | |
| $parentPageId = $parentPageIds; | |
| } | |
| else | |
| { | |
| $parentRecord = $recordNode->getParent(); | |
| $parentPageId = $parentRecord->getDmPage()->get('id'); | |
| } | |
| } | |
| elseif ($parentModule->getKey() === $module->getKey()) // parent page is a list page | |
| { | |
| $parentPageId = $parentPageIds; | |
| } | |
| else // parent page is a show page | |
| { | |
| if ($parentRecordIds !== false) | |
| { | |
| $parentRecordId = isset($parentRecordIds[$record['id']]) ? $parentRecordIds[$record['id']] : null; | |
| } | |
| else | |
| { | |
| $parentRecordId = dmDb::create($module->getModel(), $record)->getAncestorRecordId($parentModule->getModel()); | |
| } | |
| if(!$parentRecordId) | |
| { | |
| throw new dmPageMustNotExistException(sprintf('No parent record found for %s, page %s must not exist', $module->getModel(), $page['id'])); | |
| } | |
| elseif (!($parentPageId = dmArray::get($parentPageIds, $parentRecordId))) | |
| { | |
| throw new dmPageMustNotExistException(sprintf( | |
| '%s needs a parent page, %s.%s, but it does not exists for parent object %d', | |
| $module, $parentModule, 'show', $parentRecordId | |
| )); | |
| } | |
| } | |
| $modified = false; | |
| if (!$page['id']) | |
| { | |
| if (!$parentPage = $pageTable->find($parentPageId)) | |
| { | |
| throw new dmException(sprintf('parent page with id %d for new page %s was not found', $parentPageId, $page['module'].'.show')); | |
| } | |
| dmDb::table('DmPage')->create($page)->getNode()->insertAsLastChildOf($parentPage); | |
| } | |
| else | |
| { | |
| if ($this->getNodeParentId($page) != $parentPageId) | |
| { | |
| if (!$parentPage = $pageTable->find($parentPageId)) | |
| { | |
| throw new dmException(sprintf('parent page with id %d for new page %s was not found', $parentPageId, $page['module'].'.show')); | |
| } | |
| $pageRecord = dmDb::table('DmPage')->find($page['id']); | |
| $pageRecord->refresh(true); | |
| $pageRecord->getNode()->moveAsLastChildOf($parentPage); | |
| } | |
| } | |
| } | |
| protected function getNodeParentId(array $pageData) | |
| { | |
| if (null === $this->nodeParentIdStmt) | |
| { | |
| $this->nodeParentIdStmt = Doctrine_Manager::connection()->prepare('SELECT p.id | |
| FROM dm_page p | |
| WHERE p.lft < ? AND p.rgt > ? | |
| ORDER BY p.rgt ASC | |
| LIMIT 1')->getStatement(); | |
| } | |
| $this->nodeParentIdStmt->execute(array($pageData['lft'], $pageData['rgt'])); | |
| return $this->nodeParentIdStmt->fetchColumn(); | |
| } | |
| protected function getParentRecordIds(dmProjectModule $module, dmProjectModule $parentModule) | |
| { | |
| /* | |
| * if parent is local relation for module, | |
| * we can prepare parent records | |
| */ | |
| if ($module->hasLocal($parentModule)) | |
| { | |
| $local = $module->getTable()->getRelationHolder()->getLocalByClass($parentModule->getModel())->getLocal(); | |
| $query = sprintf('SELECT r.id, r.%s FROM %s r WHERE EXISTS (SELECT page.id FROM dm_page page WHERE page.module = ? AND page.action = ? AND page.record_id = r.%s)', | |
| $local, | |
| $module->getTable()->getTableName(), | |
| $local | |
| ); | |
| $_parentRecordIds = dmDb::pdo($query, array($parentModule->getKey(), 'show'), $module->getTable()->getConnection())->fetchAll(PDO::FETCH_NUM); | |
| $parentRecordIds = array(); | |
| foreach($_parentRecordIds as $_parentRecordId) | |
| { | |
| $parentRecordIds[$_parentRecordId[0]] = $_parentRecordId[1]; | |
| } | |
| } | |
| /* | |
| * if parent is association relation for module, | |
| * we can prepare parent records | |
| */ | |
| elseif ($module->hasAssociation($parentModule)) | |
| { | |
| $association = $module | |
| ->getTable() | |
| ->getRelationHolder() | |
| ->getAssociationByClass($parentModule->getModel()); | |
| $query = sprintf('SELECT association.%s, association.%s FROM %s association WHERE EXISTS (SELECT page.id FROM dm_page page WHERE page.module = ? AND page.action = ? AND page.record_id = association.%s) GROUP BY association.%s', | |
| $association->getForeign(), | |
| $association->getLocal(), | |
| $association->getAssociationTable()->getTableName(), | |
| $association->getForeign(), | |
| $association->getLocal() | |
| ); | |
| $_parentRecordIds = dmDb::pdo($query, array($parentModule->getKey(), 'show'), $module->getTable()->getConnection())->fetchAll(PDO::FETCH_NUM); | |
| $parentRecordIds = array(); | |
| foreach($_parentRecordIds as $value) | |
| { | |
| $parentRecordIds[$value[1]] = $value[0]; | |
| } | |
| } | |
| /* | |
| * parent records are to far to be prepared. | |
| * they will be evaluated later. | |
| */ | |
| else | |
| { | |
| $parentRecordIds = false; | |
| } | |
| return $parentRecordIds; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment