_prepareFullList($this->_getUnionList(false, $partId, $revisionId)); return $this->_getListTree((int)$departmentId, 0, false); } public function getWideList($departmentId = 0, $leaveEmptyDepartments = true) { if (null === $this->_wideList) { $this->_prepareFullList($this->_getUnionList()); $this->_wideList = $this->_getListTree(0, 0, $leaveEmptyDepartments); $this->_wideList['link']['process'] = Qs_SiteMap::getAliasByItem('Process_Part_'); $this->_wideList['link']['department'] = Qs_SiteMap::findFirst( null, array('type' => 'Department_'), array('type' => 'landing'), 'fullAlias' ); $menuCounter = $listCounter = 0; $menuDivider = $this->_wideList['menuCount'] / self::MENU_COLUMNS; $listDivider = $this->_wideList['count'] / self::LIST_COLUMNS; $optionDivider = $this->_wideList['count'] / self::OPTION_COLUMNS; foreach ($this->_wideList['list'] as &$row) { $menuCounter += $row['menuCount']; $listCounter += $row['count']; if ($menuCounter > $menuDivider) { $row['menuBreak'] = ($menuCounter - $menuDivider - $row['menuCount'] / 2 > 0) ? 'before' : 'after'; $menuDivider += $this->_wideList['menuCount'] / self::MENU_COLUMNS; } if ($listCounter > $listDivider) { $row['break'] = ($listCounter - $listDivider - $row['count'] / 2 > 0) ? 'before' : 'after'; $listDivider += $this->_wideList['count'] / self::LIST_COLUMNS; } if ($listCounter > $optionDivider) { $row['optionBreak'] = ($listCounter - $optionDivider - $row['count'] / 2 > 0) ? 'before' : 'after'; $optionDivider += $this->_wideList['count'] / self::OPTION_COLUMNS; } } $this->_wideList; } $wideList = $this->_wideList; if ($departmentId) { unset($wideList['list']); $wideList = array_merge($wideList, $this->_findDepartmentInWideList($departmentId)); } return $wideList; } protected function _findDepartmentInWideList($departmentId, array $list = null) { if (null === $list) { $list = $this->_wideList; } if (array_key_exists('list', $list)) { foreach ($list['list'] as $department) { if ($department['departmentId'] != $departmentId) { $department = $this->_findDepartmentInWideList($departmentId, $department); } if ($department) { return $department; } } } return null; } protected function _getListTree($parentId = 0, $level = 0, $leaveEmptyDepartments = true) { $result = array('count' => 1, 'menuCount' => 0); if ($level <= 2) { $result['menuCount'] = 1; } if (array_key_exists($parentId, $this->_fullList)) { $result['list'] = $this->_fullList[$parentId]; foreach ($result['list'] as $key => &$row) { $row = array_merge($row, $this->_getListTree($row['departmentId'], $level + 1, $leaveEmptyDepartments)); if ($row['departmentId'] && empty($row['list']) && !$leaveEmptyDepartments) { unset($result['list'][$key]); } else { $result['count'] += $row['count']; $result['menuCount'] += $row['menuCount']; } } } return $result; } protected function _prepareFullList(array $list) { $this->_fullList = array(); foreach ($list as $row) { $key = $row['parentId'] ? $row['parentId'] : ($row['processParentId'] ? $row['processParentId'] : 0); $this->_fullList[$key][] = $row; } return $this->_fullList; } protected function _getUnionList($reorder = false, $partId = null, $revisionId = null) { $select = $this->_db->select(); $columns = array( 'sorter', 'orderId' => 'id' ); if ($partId && $revisionId) { $mediaSelect = $this->_db->select() ->from($this->pairMedia, 'COUNT(Media.id)') ->where('partId = ?', $partId) ->where('processId = DepartmentAndProcessSorter.processId') ->where('revisionStart <= ?', $revisionId) ->where('revisionEnd > ? OR revisionEnd IS NULL', $revisionId); $columns['mediaCount'] = new Zend_Db_Expr('(' . $mediaSelect . ')'); } $select->from($this->_getPair('DepartmentAndProcessSorter'), $columns); if ($reorder) { $select = $this->_where4AllSorter($select); } $select->order('sorter'); $select->joinLeft( $this->_getPair('Department'), 'DepartmentAndProcessSorter.departmentId = Department.id', array('departmentId' => 'id', 'departmentName' => 'name', 'parentId') ); $userId = App_User_Auth::getInstance()->hasIdentity() ? App_User_Auth::getInstance()->getData('id') : null; $unblockable = "CASE WHEN (DATEADD(hour, %1\$d, blockedAt) < GETDATE()) THEN 'y' ELSE 'n' END"; $unblockable = sprintf($unblockable, App_Process_Obj::UNBLOCK_TIME, $userId); $editable = sprintf("CASE WHEN (blockedAt IS NULL OR blockedBy = %1\$d) THEN 'y' ELSE 'n' END", $userId); $select->joinLeft( $this->_getPair('Process'), "DepartmentAndProcessSorter.processId = Process.id AND Process.new = 'n'", array('processId' => 'id', 'processName' => 'name', 'processParentId' => 'departmentId', 'blockedAt', 'unblockable' => new Zend_Db_Expr($unblockable), 'editable' => new Zend_Db_Expr($editable), 'isMedia', 'nonExport') ); $select->joinLeft($this->pairUser, '"User".id = Process.blockedBy', array('firstName', 'lastName')); if ($partId) { $select->joinLeft($this->pairPart2Process, 'Part2Process.processId = Process.id', array()); $select->where('Department.id IS NOT NULL OR Part2Process.partId = ?', $partId); } else { $select->where('Process.id IS NOT NULL OR Department.id IS NOT NULL'); } return $this->_db->fetchAll($select); } protected function _where4AllSorter(Zend_Db_Select $select = null) { $select = parent::_where4Sorter($select); $select->where('parentId = ?', $this->getPrimaryKey(), Qs_Db::INT_TYPE); $select->orWhere('Process.departmentId = ?', $this->getPrimaryKey(), Qs_Db::INT_TYPE); $select->where('Process.new = ?', 'n'); return $select; } public function getParentIdById($id) { $select = $this->_db->select(); $select->from($this->pair, 'parentId') ->where('id = ?', $id, Qs_Db::INT_TYPE); return $this->_db->fetchOne($select); } protected function _insertDependency() { $order = array( 'departmentId' => $this->_primaryKey, 'processId' => null, 'sorter' => $this->_getDependenceSorter() ); $this->tableDepartmentAndProcessSorter->insert($order); } protected function _getDependenceSorter($insertPlacement = null) { if (null === $insertPlacement) { $insertPlacement = $this->_insertPlacement; } if ('PREPEND' == $insertPlacement) { $function = 'MIN'; $diff = -1; } elseif ('APPEND' == $insertPlacement) { $function = 'MAX'; $diff = 1; } else { throw new Qs_Db_Exception('Unknown insert placement: ' . $this->_insertPlacement); } $select = $this->_db->select(); $select->from($this->_getPair('DepartmentAndProcessSorter'), "{$function}(DepartmentAndProcessSorter.sorter)"); $statement = $select->query(); if (null === ($sorter = $statement->fetchColumn(0))){ return 0; } return $sorter + $diff; } public function delete() { parent::delete(); $this->_db->delete( $this->_getPair('DepartmentAndProcessSorter'), $this->_db->quoteInto('departmentId = ?', $this->_primaryKey) ); return $this; } public function getReorderOptions($keyColumn, $titleColumn) { $keyColumn = 'orderId'; $list = $this->_getUnionList(true); $options = array(); foreach ($list as $row) { if (isset($row['departmentId'])) { $titleColumn = 'departmentName'; } else { $titleColumn = 'processName'; } $options[$row[$keyColumn]] = $row[$titleColumn]; } return $options; } protected function _createSorterUpdateQuery($tableAlias, $sorter, $id) { return $this->_db->quoteInto( 'UPDATE ' . $this->_getTableName($tableAlias) .' SET sorter = ' . $sorter . ' WHERE ' . $this->_getTableName($tableAlias) . '.id = ?; ', $id, Qs_Db::INT_TYPE ); } public function updateOrder(array $order) { $changedOrder = $this->_getChangedOrder($order); $query = ''; foreach ($order as $sorter => $id) { $query .= $this->_createSorterUpdateQuery('DepartmentAndProcessSorter', $sorter, $id); if ($changedOrder[$id]['departmentId']) { $query .= $this->_createSorterUpdateQuery('Department', $sorter, $id); } else { $query .= $this->_createSorterUpdateQuery('Process', $sorter, $id); } } $this->_db->query($query); } public function getChildCountByKey() { $select = $this->_db->select(); $select->from($this->pair, 'COUNT(*)') ->where('parentId = ?', $this->getPrimaryKey(), Qs_Db::INT_TYPE); return $this->_db->fetchOne($select); } public function getProcessCountByKey() { $select = $this->_db->select(); $select->from($this->_getPair('Process'), 'COUNT(*)') ->where('departmentId = ?', $this->getPrimaryKey(), Qs_Db::INT_TYPE) ->where('new = ?', 'n'); return $this->_db->fetchOne($select); } protected function _getChangedOrder($order) { $select = $this->_db->select(); $select->from($this->_getPair('DepartmentAndProcessSorter')); $select->where('DepartmentAndProcessSorter.id IN(?)', $order); return $this->_db->fetchAssoc($select); } public function getParentData($id) { $select = $this->_db->select(); $select->from($this->pair) ->where('id = ?', $id, Qs_Db::INT_TYPE); return $this->_db->fetchRow($select); } public function getTopLevelDepartment($userId) { $select = $this->_db->select(); $select->from($this->_getPair('Department'), array('id', 'Name')); $select->join( $this->_getPair('User2Department'), 'User2Department.departmentId = Department.id', array() ); $select->joinLeft( $this->_getPair('DepartmentAndProcessSorter'), 'DepartmentAndProcessSorter.departmentId = Department.id', array() ); $select->where('User2Department.userId = ?', $userId, Qs_Db::INT_TYPE); $select->order('DepartmentAndProcessSorter.sorter'); return $this->_db->fetchPairs($select); } }