예제 #1
0
 /**
  *
  *
  * @param
  *
  * @return
  */
 protected static function findNoIndex($parameters)
 {
     $dbConnection = Main\HttpApplication::getConnection();
     $dbHelper = $dbConnection->getSqlHelper();
     // tables
     $locationTable = Location\LocationTable::getTableName();
     $locationNameTable = Location\Name\LocationTable::getTableName();
     $locationGroupTable = Location\GroupLocationTable::getTableName();
     $locationSiteTable = Location\SiteLocationTable::getTableName();
     $locationTypeTable = Location\TypeTable::getTableName();
     //////////////////////////////////
     // sql parameters prepare
     //////////////////////////////////
     $filter = static::parseFilter($parameters['filter']);
     if (strlen($filter['SITE_ID']['VALUE'])) {
         $filterSite = $dbHelper->forSql(substr($filter['SITE_ID']['VALUE'], 0, 2));
         $hasLocLinks = Location\SiteLocationTable::checkLinkUsage($filterSite, Location\SiteLocationTable::DB_LOCATION_FLAG);
         $hasGrpLinks = Location\SiteLocationTable::checkLinkUsage($filterSite, Location\SiteLocationTable::DB_GROUP_FLAG);
         $doFilterBySite = true;
     }
     if (strlen($filter['PHRASE']['VALUE'])) {
         $doFilterByName = true;
         $filterName = ToUpper($dbHelper->forSql($filter['PHRASE']['VALUE']));
     }
     if (intval($filter['ID']['VALUE'])) {
         $doFilterById = true;
         $filterId = intval($filter['ID']['VALUE']);
     }
     if (intval($filter['CODE']['VALUE'])) {
         $doFilterByCode = true;
         $filterCode = $dbHelper->forSql($filter['CODE']['VALUE']);
     }
     $doFilterByLang = true;
     if (strlen($filter['NAME.LANGUAGE_ID']['VALUE'])) {
         $filterLang = $dbHelper->forSql(substr($filter['NAME.LANGUAGE_ID']['VALUE'], 0, 2));
     } else {
         $filterLang = LANGUAGE_ID;
     }
     if (isset($filter['PARENT_ID']) && intval($filter['PARENT_ID']['VALUE']) >= 0) {
         $doFilterByParent = true;
         $filterParentId = intval($filter['PARENT_ID']['VALUE']);
     }
     if (intval($filter['TYPE_ID']['VALUE'])) {
         $doFilterByType = true;
         $filterTypeId = intval($filter['TYPE_ID']['VALUE']);
     }
     // filter select fields
     if (!is_array($parameters['select'])) {
         $parameters['select'] = array();
     }
     $map = Location\LocationTable::getMap();
     $nameAlias = false;
     foreach ($parameters['select'] as $alias => $field) {
         if ($field == 'CHILD_CNT') {
             $doCountChildren = true;
         }
         if ($field == 'NAME.NAME') {
             $nameAlias = $alias;
         }
         if (!isset($map[$field]) || !in_array($map[$field]['data_type'], array('integer', 'string', 'float', 'boolean')) || isset($map[$field]['expression'])) {
             unset($parameters['select'][$alias]);
         }
     }
     //////////////////////////////////
     // sql query build
     //////////////////////////////////
     // mandatory fields to be selected anyway
     // alias => field
     $fields = array('L.ID' => 'L.ID', 'L.CODE' => 'L.CODE', 'L.SORT' => 'L.SORT', 'LT_SORT' => 'LT.DISPLAY_SORT');
     if ($nameAlias === false || !preg_match('#^[a-zA-Z0-9]+$#', $nameAlias)) {
         $fields['NAME'] = 'LN.NAME';
     } else {
         $fields[$nameAlias] = 'LN.NAME';
     }
     $fields = array_merge($fields, array('L.LEFT_MARGIN' => 'L.LEFT_MARGIN', 'L.RIGHT_MARGIN' => 'L.RIGHT_MARGIN'));
     $groupFields = $fields;
     // additional fields to select
     foreach ($parameters['select'] as $alias => $fld) {
         $lFld = 'L.' . $fld;
         // check if field is already selected
         if ((string) $alias === (string) intval($alias)) {
             // already selected
             if (in_array($lFld, $fields)) {
                 continue;
             }
             $fields[$lFld] = $lFld;
             //$groupFields[$lFld] = $lFld;
         } else {
             if (isset($fields[$alias])) {
                 continue;
             }
             $fields[$alias] = $lFld;
             //$groupFields[$alias] = $lFld;
         }
         $groupFields[$lFld] = $lFld;
     }
     if ($doCountChildren) {
         $fields['CHILD_CNT'] = 'COUNT(LC.ID)';
     }
     // make select sql
     $selectSql = array();
     foreach ($fields as $alias => $fld) {
         if ($fld == $alias) {
             $selectSql[] = $fld;
         } else {
             $selectSql[] = $fld . ' as ' . $alias;
         }
     }
     $selectSql = implode(', ', $selectSql);
     //$groupSql = implode(', ', array_keys($groupFields));
     $groupSql = implode(', ', $groupFields);
     $mainSql = "select {$selectSql}\n\t\t\t\t\t\tfrom {$locationTable} L \n\t\t\t\t\t\t\tinner join {$locationNameTable} LN on L.ID = LN.LOCATION_ID\n\t\t\t\t\t\t\tinner join {$locationTypeTable} LT on L.TYPE_ID = LT.ID " . ($doCountChildren ? "\n\t\t\t\t\t\t\t\tleft join {$locationTable} LC on L.ID = LC.PARENT_ID\n\t\t\t\t\t\t\t" : "") . " \n\n\t\t\t\t\t\t%SITE_FILTER_CONDITION%\n\n\t\t\t\t\t\twhere \n\n\t\t\t\t\t\t\t%MAIN_FILTER_CONDITION%\n\n\t\t\t\t\t\t\t%GROUP_BY%\n\t\t\t\t\t\t\t";
     $where = array();
     if ($doFilterByLang) {
         $where[] = "LN.LANGUAGE_ID = '" . $filterLang . "'";
     }
     if ($doFilterByParent) {
         $where[] = "L.PARENT_ID = '" . $filterParentId . "'";
     }
     if ($doFilterById) {
         $where[] = "L.ID = '" . $filterId . "'";
     }
     if ($doFilterByCode) {
         $where[] = "L.CODE = '" . $filterCode . "'";
     }
     if ($doFilterByType) {
         $where[] = "L.TYPE_ID = '" . $filterTypeId . "'";
     }
     if ($doFilterByName) {
         $where[] = "LN.NAME_UPPER like '" . $filterName . "%'";
     }
     $mainSql = str_replace('%MAIN_FILTER_CONDITION%', implode(' and ', $where), $mainSql);
     $needDistinct = false;
     $unionized = false;
     $artificialNav = false;
     if (!$doFilterBySite) {
         $sql = str_replace('%SITE_FILTER_CONDITION%', '', $mainSql);
     } else {
         $sql = array();
         if ($hasLocLinks) {
             $sql[] = str_replace('%SITE_FILTER_CONDITION%', "\n\n\t\t\t\t\tinner join {$locationTable} L2 on L2.LEFT_MARGIN <= L.LEFT_MARGIN and L2.RIGHT_MARGIN >= L.RIGHT_MARGIN\n\t\t\t\t\tinner join {$locationSiteTable} LS2 on L2.ID = LS2.LOCATION_ID and LS2.LOCATION_TYPE = 'L' and LS2.SITE_ID = '{$filterSite}'\n\n\t\t\t\t", $mainSql);
         }
         if ($hasGrpLinks) {
             $sql[] = str_replace('%SITE_FILTER_CONDITION%', "\n\n\t\t\t\t\tinner join {$locationTable} L2 on L2.LEFT_MARGIN <= L.LEFT_MARGIN and L2.RIGHT_MARGIN >= L.RIGHT_MARGIN\n\t\t\t\t\tinner join {$locationGroupTable} LG on LG.LOCATION_ID = L2.ID\n\t\t\t\t\tinner join {$locationSiteTable} LS2 on LG.LOCATION_GROUP_ID = LS2.LOCATION_ID and LS2.LOCATION_TYPE = 'G' and LS2.SITE_ID = '{$filterSite}'\n\n\t\t\t\t", $mainSql);
             $useDistinct = true;
         }
         $cnt = count($sql);
         if ($cnt == 1) {
             $needDistinct = true;
         } else {
             // UNION removes duplicates, so distinct is required only when no union here
             $unionized = true;
         }
         $sql = ($cnt > 1 ? '(' : '') . implode(') union (', $sql) . ($cnt > 1 ? ')' : '');
     }
     // set groupping if needed
     $sql = str_replace('%GROUP_BY%', $needDistinct || $doCountChildren ? "group by {$groupSql}" : '', $sql);
     if (!is_array($parameters['order'])) {
         $sql .= " order by 3, 4 asc, 5";
     } else {
         // currenly spike
         if (isset($parameters['order']['NAME.NAME'])) {
             $sql .= " order by 5 " . ($parameters['order']['NAME.NAME'] == 'asc' ? 'asc' : 'desc');
         }
     }
     $offset = intval($parameters['offset']);
     $limit = intval($parameters['limit']);
     if ($limit) {
         if ($dbConnection->getType() == 'mssql') {
             // due to huge amount of limitations of windowed functions in transact, using artificial nav here
             // (does not support UNION and integer indices in ORDER BY)
             $artificialNav = true;
         } else {
             $sql = $dbHelper->getTopSql($sql, $limit, $offset);
         }
     }
     $res = $dbConnection->query($sql);
     if ($artificialNav) {
         $result = array();
         $i = -1;
         while ($item = $res->fetch()) {
             $i++;
             if ($i < $offset) {
                 continue;
             }
             if ($i >= $offset + $limit) {
                 break;
             }
             $result[] = $item;
         }
         return new DB\ArrayResult($result);
     } else {
         return $res;
     }
 }