FixTreeCommand.php (4215B)
1 <?php 2 3 namespace PartKeepr\CoreBundle\Command; 4 5 use Doctrine\ORM\EntityManager; 6 use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; 7 use Symfony\Component\Console\Input\InputInterface; 8 use Symfony\Component\Console\Output\OutputInterface; 9 10 class FixTreeCommand extends ContainerAwareCommand 11 { 12 /** 13 * @var EntityManager 14 */ 15 private $entityManager; 16 17 public function configure() 18 { 19 parent::configure(); 20 $this->setName('partkeepr:fix-category-trees'); 21 $this->setDescription('Fixes the category trees'); 22 } 23 24 public function execute(InputInterface $input, OutputInterface $output) 25 { 26 $this->entityManager = $this->getContainer()->get("doctrine.orm.default_entity_manager"); 27 $this->fixTree('PartCategory'); 28 $this->fixTree('FootprintCategory'); 29 $this->fixTree('StorageLocationCategory'); 30 } 31 32 /** 33 * Fixes the tree for a given table due to the migration of doctrine2-nestedset to DoctrineExtensions. 34 * 35 * @param string $table The table name to fix 36 * 37 * @throws \Doctrine\DBAL\DBALException 38 */ 39 public function fixTree($table) 40 { 41 $nodes = $this->getNodeIds($table); 42 43 $queryBuilder = $this->entityManager->getConnection()->createQueryBuilder(); 44 $queryBuilder->update($table) 45 ->set('parent_id', ':parent') 46 ->set('root', ':root') 47 ->set('lvl', ':level') 48 ->where('id = :id'); 49 50 foreach ($nodes as $node) { 51 $parent = $this->fetchParent($table, $node['id']); 52 $level = $this->getLevel($table, $node['id']); 53 54 if ($parent !== false) { 55 $this->entityManager->getConnection()->executeUpdate( 56 $queryBuilder->getSQL(), 57 [ 58 ':parent' => $parent, 59 ':id' => $node['id'], 60 ':level' => $level, 61 ':root' => 1, 62 ] 63 ); 64 } else { 65 $this->entityManager->getConnection()->executeUpdate( 66 $queryBuilder->getSQL(), 67 [ 68 ':parent' => null, 69 ':id' => $node['id'], 70 ':root' => 1, 71 ':level' => 0, 72 ] 73 ); 74 } 75 } 76 } 77 78 /** 79 * Fetches the parent node for a table and ID. 80 * 81 * @param $table 82 * @param $id 83 * 84 * @return mixed 85 */ 86 public function fetchParent($table, $id) 87 { 88 $queryBuilder = $this->entityManager->getConnection()->createQueryBuilder(); 89 90 $queryBuilder->select('parent.id') 91 ->from($table, 'node') 92 ->from($table, 'parent') 93 ->where('parent.lft < node.lft') 94 ->andWhere('parent.rgt > node.rgt') 95 ->andWhere('node.id = :nodeid') 96 ->orderBy('parent.rgt - parent.lft') 97 ->setMaxResults(1); 98 99 return $this->entityManager->getConnection()->fetchColumn($queryBuilder->getSQL(), [':nodeid' => $id], 0); 100 } 101 102 /** 103 * Returns the node IDs for the table. 104 * 105 * @param $table 106 * 107 * @return array 108 */ 109 public function getNodeIds($table) 110 { 111 $qb = $this->entityManager->getConnection()->createQueryBuilder(); 112 113 $qb->select('id') 114 ->from($table) 115 ->orderBy('id', 'ASC'); 116 117 return $this->entityManager->getConnection()->fetchAll($qb->getSQL()); 118 } 119 120 /** 121 * Returns the level for a given table and ID. 122 * 123 * @param $table 124 * @param $id 125 * 126 * @return mixed 127 */ 128 public function getLevel($table, $id) 129 { 130 $qb = $this->entityManager->getConnection()->createQueryBuilder(); 131 132 $qb->select('COUNT(*) AS level') 133 ->from($table, 'node') 134 ->from($table, 'parent') 135 ->where('node.lft > parent.lft') 136 ->andWhere('node.lft < parent.rgt') 137 ->andWhere('node.id = :nodeid'); 138 139 return $this->entityManager->getConnection()->fetchAssoc($qb->getSQL(), [':nodeid' => $id])['level']; 140 } 141 }