| Total Complexity | 181 |
| Total Lines | 1124 |
| Duplicated Lines | 0 % |
| Changes | 6 | ||
| Bugs | 0 | Features | 0 |
Complex classes like RDatabaseSqlparserSqltranslation often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use RDatabaseSqlparserSqltranslation, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 19 | class RDatabaseSqlparserSqltranslation extends RTranslationHelper |
||
| 20 | { |
||
| 21 | /** |
||
| 22 | * The options. |
||
| 23 | * |
||
| 24 | * @var array |
||
| 25 | */ |
||
| 26 | private static $options = array(); |
||
| 27 | |||
| 28 | /** |
||
| 29 | * The options. |
||
| 30 | * |
||
| 31 | * @var array |
||
| 32 | */ |
||
| 33 | private static $parsedQueries = array(); |
||
| 34 | |||
| 35 | /** |
||
| 36 | * Checks if tables inside query have translatable tables and fields and fetch appropriate |
||
| 37 | * value from translations table |
||
| 38 | * |
||
| 39 | * @param string $sql SQL query |
||
| 40 | * @param string $prefix Table prefix |
||
| 41 | * @param string $language Language tag you want to fetch translation from |
||
| 42 | * @param array $translationTables List of translation tables |
||
| 43 | * |
||
| 44 | * @return mixed Parsed query with added table joins and fields if found |
||
| 45 | */ |
||
| 46 | public static function parseSelectQuery($sql = '', $prefix = '', $language = 'en-GB', $translationTables = array()) |
||
|
|
|||
| 47 | { |
||
| 48 | if (empty($translationTables)) |
||
| 49 | { |
||
| 50 | // We do not have any translation table to check |
||
| 51 | return null; |
||
| 52 | } |
||
| 53 | |||
| 54 | try |
||
| 55 | { |
||
| 56 | $hashedQueryKey = md5($sql . $language); |
||
| 57 | |||
| 58 | if (isset(self::$parsedQueries[$hashedQueryKey])) |
||
| 59 | { |
||
| 60 | return self::$parsedQueries[$hashedQueryKey]; |
||
| 61 | } |
||
| 62 | |||
| 63 | $db = JFactory::getDbo(); |
||
| 64 | self::$parsedQueries[$hashedQueryKey] = null; |
||
| 65 | $sqlParser = new RDatabaseSqlparserSqlparser($sql); |
||
| 66 | $parsedSql = $sqlParser->parsed; |
||
| 67 | |||
| 68 | if (!empty($parsedSql)) |
||
| 69 | { |
||
| 70 | $foundTables = array(); |
||
| 71 | $originalTables = array(); |
||
| 72 | $parsedSqlColumns = null; |
||
| 73 | $subQueryFound = false; |
||
| 74 | $parsedSql = self::parseTableReplacements($parsedSql, $translationTables, $foundTables, $originalTables, $language, $subQueryFound); |
||
| 75 | |||
| 76 | if (empty($foundTables) && !$subQueryFound) |
||
| 77 | { |
||
| 78 | // We did not find any table to translate |
||
| 79 | return null; |
||
| 80 | } |
||
| 81 | |||
| 82 | // Prepare field replacement |
||
| 83 | $columns = array(); |
||
| 84 | $columnFound = false; |
||
| 85 | $parsedSqlColumns = $parsedSql; |
||
| 86 | |||
| 87 | // Prepare column replacements |
||
| 88 | foreach ($foundTables as $foundTable) |
||
| 89 | { |
||
| 90 | // Get all columns from that table |
||
| 91 | $tableColumns = (array) $translationTables[$foundTable['originalTableName']]->columns; |
||
| 92 | $originalTableColumns = RTranslationTable::getTableColumns($foundTable['originalTableName']); |
||
| 93 | |||
| 94 | if (!empty($tableColumns)) |
||
| 95 | { |
||
| 96 | $selectAllOriginalColumn = $foundTable['alias']['originalName'] . '.*'; |
||
| 97 | $columnAll = array(); |
||
| 98 | $columnAll['table'] = $foundTable; |
||
| 99 | $columnAll['columnName'] = $selectAllOriginalColumn; |
||
| 100 | $columnAll['base_expr'] = self::addBaseColumns($originalTableColumns, $tableColumns, $foundTable['alias']['originalName']); |
||
| 101 | |||
| 102 | foreach ($tableColumns as $tableColumn) |
||
| 103 | { |
||
| 104 | $column = array(); |
||
| 105 | $fallbackValue = $foundTable['alias']['originalName'] . '.' . $tableColumn; |
||
| 106 | |||
| 107 | // Check to see if fallback option is turned on, if it is not then we set empty string as value |
||
| 108 | if (!self::getOption('translationFallback', true)) |
||
| 109 | { |
||
| 110 | // Additionally we check for columns that must have a fallback (ex. state, publish, etc.) |
||
| 111 | if (empty($translationTables[$foundTable['originalTableName']]->fallbackColumns) |
||
| 112 | || !in_array($tableColumn, $translationTables[$foundTable['originalTableName']]->fallbackColumns)) |
||
| 113 | { |
||
| 114 | $fallbackValue = $db->q(''); |
||
| 115 | } |
||
| 116 | } |
||
| 117 | |||
| 118 | // If column is primary key we do not need to translate it |
||
| 119 | if (in_array($tableColumn, $translationTables[$foundTable['originalTableName']]->primaryKeys)) |
||
| 120 | { |
||
| 121 | $column['base_expr'] = $foundTable['alias']['originalName'] . '.' . $tableColumn; |
||
| 122 | } |
||
| 123 | else |
||
| 124 | { |
||
| 125 | $column['base_expr'] = '' |
||
| 126 | . 'COALESCE(' |
||
| 127 | . $foundTable['alias']['name'] . '.' . $tableColumn |
||
| 128 | . ',' . $fallbackValue |
||
| 129 | . ')'; |
||
| 130 | } |
||
| 131 | |||
| 132 | $column['alias'] = $db->qn($tableColumn); |
||
| 133 | $column['table'] = $foundTable; |
||
| 134 | $column['columnName'] = $tableColumn; |
||
| 135 | |||
| 136 | $columns[] = $column; |
||
| 137 | |||
| 138 | if (!empty($columnAll['base_expr'])) |
||
| 139 | { |
||
| 140 | $columnAll['base_expr'] .= ','; |
||
| 141 | } |
||
| 142 | |||
| 143 | $columnAll['base_expr'] .= $column['base_expr'] . ' AS ' . $db->qn($tableColumn); |
||
| 144 | } |
||
| 145 | |||
| 146 | $columns[] = $columnAll; |
||
| 147 | } |
||
| 148 | } |
||
| 149 | |||
| 150 | if (!empty($foundTables)) |
||
| 151 | { |
||
| 152 | $parsedSqlColumns = self::parseColumnReplacements($parsedSqlColumns, $columns, $translationTables, $columnFound); |
||
| 153 | } |
||
| 154 | |||
| 155 | // We are only returning parsed SQL if we found at least one column in translation table |
||
| 156 | if ($columnFound || $subQueryFound) |
||
| 157 | { |
||
| 158 | $sqlCreator = new RDatabaseSqlparserSqlcreator($parsedSqlColumns); |
||
| 159 | self::$parsedQueries[$hashedQueryKey] = $sqlCreator->created; |
||
| 160 | |||
| 161 | return self::$parsedQueries[$hashedQueryKey]; |
||
| 162 | } |
||
| 163 | } |
||
| 164 | } |
||
| 165 | catch (Exception $e) |
||
| 166 | { |
||
| 167 | return null; |
||
| 168 | } |
||
| 169 | |||
| 170 | return null; |
||
| 171 | } |
||
| 172 | |||
| 173 | /** |
||
| 174 | * Checks if this query is qualified for translation and parses query |
||
| 175 | * |
||
| 176 | * @param string $sql SQL query |
||
| 177 | * @param string $prefix Table prefix |
||
| 178 | * |
||
| 179 | * @return mixed Parsed query with added table joins and fields if found |
||
| 180 | */ |
||
| 181 | public static function buildTranslationQuery($sql = '', $prefix = '') |
||
| 182 | { |
||
| 183 | $db = JFactory::getDbo(); |
||
| 184 | |||
| 185 | $selectedLanguage = !empty($db->forceLanguageTranslation) ? $db->forceLanguageTranslation : JFactory::getLanguage()->getTag(); |
||
| 186 | $queryArray = explode(',', (string) $sql); |
||
| 187 | $hashValues = array(); |
||
| 188 | |||
| 189 | // Replace long amount of numeric values if found. They do not have any affects for translation parser |
||
| 190 | if (count($queryArray) > 50) |
||
| 191 | { |
||
| 192 | $index = 0; |
||
| 193 | $numbers = array($index => array()); |
||
| 194 | |||
| 195 | foreach ($queryArray as $key => $value) |
||
| 196 | { |
||
| 197 | if (is_numeric(trim($value))) |
||
| 198 | { |
||
| 199 | if (!array_key_exists($index, $numbers)) |
||
| 200 | { |
||
| 201 | $numbers[$index] = array(); |
||
| 202 | } |
||
| 203 | |||
| 204 | $numbers[$index][$key] = $value; |
||
| 205 | unset($queryArray[$key]); |
||
| 206 | } |
||
| 207 | else |
||
| 208 | { |
||
| 209 | if (!empty($numbers[$index])) |
||
| 210 | { |
||
| 211 | $index++; |
||
| 212 | } |
||
| 213 | } |
||
| 214 | } |
||
| 215 | |||
| 216 | foreach ($numbers as $index => $values) |
||
| 217 | { |
||
| 218 | if (count($values) < 10) |
||
| 219 | { |
||
| 220 | foreach ($values as $key => $value) |
||
| 221 | { |
||
| 222 | $queryArray[$key] = $value; |
||
| 223 | } |
||
| 224 | } |
||
| 225 | else |
||
| 226 | { |
||
| 227 | $firstKey = key($values); |
||
| 228 | $hashValue = $db->q(md5(json_encode($values))); |
||
| 229 | $queryArray[$firstKey] = $hashValue; |
||
| 230 | $hashValues[$hashValue] = $values; |
||
| 231 | } |
||
| 232 | } |
||
| 233 | |||
| 234 | unset($numbers); |
||
| 235 | ksort($queryArray); |
||
| 236 | $sql = implode(',', $queryArray); |
||
| 237 | } |
||
| 238 | |||
| 239 | if (!empty($db->parseTablesBefore)) |
||
| 240 | { |
||
| 241 | foreach ($db->parseTablesBefore as $tableGroup) |
||
| 242 | { |
||
| 243 | $sql = self::parseSelectQuery($sql, $prefix, $tableGroup->language, $tableGroup->translationTables); |
||
| 244 | } |
||
| 245 | } |
||
| 246 | |||
| 247 | // If we have a SELECT in the query then we check the reset of the params |
||
| 248 | $validSelect = (!empty($sql) && stristr(mb_strtolower($sql), 'select')); |
||
| 249 | |||
| 250 | // If the language is the default, there is no reason to translate |
||
| 251 | $isDefaultLanguage = (RTranslationHelper::getSiteLanguage() == $selectedLanguage) && !self::getOption('forceTranslateDefault', false); |
||
| 252 | |||
| 253 | // If this is the admin, but no an API request we shouldn't translate |
||
| 254 | $isAdmin = RTranslationHelper::isAdmin(); |
||
| 255 | |||
| 256 | /** |
||
| 257 | * Basic check for translations, translation will not be inserted if: |
||
| 258 | * If we do not have SELECT anywhere in query |
||
| 259 | * If current language is site default language |
||
| 260 | * If we are in administration |
||
| 261 | */ |
||
| 262 | if (!$validSelect |
||
| 263 | || $isDefaultLanguage |
||
| 264 | || ($isAdmin && !self::getOption('translateInAdmin', false))) |
||
| 265 | { |
||
| 266 | if (empty($db->parseTablesBefore) && empty($db->parseTablesAfter)) |
||
| 267 | { |
||
| 268 | return null; |
||
| 269 | } |
||
| 270 | } |
||
| 271 | |||
| 272 | $translationTables = RTranslationTable::getInstalledTranslationTables(); |
||
| 273 | $translationTables = RTranslationHelper::removeFromEditForm($translationTables); |
||
| 274 | $sql = self::parseSelectQuery($sql, $prefix, $selectedLanguage, $translationTables); |
||
| 275 | |||
| 276 | if (!empty($db->parseTablesAfter)) |
||
| 277 | { |
||
| 278 | foreach ($db->parseTablesAfter as $tableGroup) |
||
| 279 | { |
||
| 280 | $sql = self::parseSelectQuery($sql, $prefix, $tableGroup->language, $tableGroup->translationTables); |
||
| 281 | } |
||
| 282 | } |
||
| 283 | |||
| 284 | // Turn back real long amount of numeric values |
||
| 285 | foreach ($hashValues as $hash => $values) |
||
| 286 | { |
||
| 287 | $sql = str_replace($hash, implode(',', $values), $sql); |
||
| 288 | } |
||
| 289 | |||
| 290 | return $sql; |
||
| 291 | } |
||
| 292 | |||
| 293 | /** |
||
| 294 | * Recursive method which go through every array and joins table if we have found the match |
||
| 295 | * |
||
| 296 | * @param array $parsedSqlColumns Parsed SQL in array format |
||
| 297 | * @param array $columns Found replacement tables |
||
| 298 | * @param array $translationTables List of translation tables |
||
| 299 | * @param bool &$columnFound Found at least one column from original table |
||
| 300 | * @param bool $addAlias Should we add alias after column name |
||
| 301 | * |
||
| 302 | * @return array Parsed query with added table joins if found |
||
| 303 | */ |
||
| 304 | public static function parseColumnReplacements($parsedSqlColumns, $columns, $translationTables, &$columnFound, $addAlias = true) |
||
| 305 | { |
||
| 306 | if (!empty($parsedSqlColumns) && is_array($parsedSqlColumns)) |
||
| 307 | { |
||
| 308 | $db = JFactory::getDbo(); |
||
| 309 | |||
| 310 | // Replace all Tables and keys |
||
| 311 | foreach ($parsedSqlColumns as $groupColumnsKey => $parsedColumnGroup) |
||
| 312 | { |
||
| 313 | if (!empty($parsedColumnGroup)) |
||
| 314 | { |
||
| 315 | $filteredGroup = array(); |
||
| 316 | |||
| 317 | foreach ($parsedColumnGroup as $tagKey => $tagColumnsValue) |
||
| 318 | { |
||
| 319 | $column = null; |
||
| 320 | |||
| 321 | if (!empty($tagColumnsValue['expr_type']) && $tagColumnsValue['expr_type'] == 'colref') |
||
| 322 | { |
||
| 323 | $column = self::getNameIfIncluded($tagColumnsValue['base_expr'], '', $columns, false, $groupColumnsKey); |
||
| 324 | |||
| 325 | if (!empty($column)) |
||
| 326 | { |
||
| 327 | $primaryKey = ''; |
||
| 328 | |||
| 329 | if (!empty($translationTables[$column['table']['originalTableName']]->primaryKeys)) |
||
| 330 | { |
||
| 331 | foreach ($translationTables[$column['table']['originalTableName']]->primaryKeys as $primaryKeyValue) |
||
| 332 | { |
||
| 333 | $primaryKey = self::getNameIfIncluded( |
||
| 334 | $primaryKeyValue, |
||
| 335 | $column['table']['alias']['originalName'], |
||
| 336 | array($tagColumnsValue['base_expr']), |
||
| 337 | false, |
||
| 338 | $groupColumnsKey |
||
| 339 | ); |
||
| 340 | |||
| 341 | if (empty($primaryKey)) |
||
| 342 | { |
||
| 343 | break; |
||
| 344 | } |
||
| 345 | } |
||
| 346 | } |
||
| 347 | |||
| 348 | // This is primary key so if only this is used in query then we do not need to parse it |
||
| 349 | if (empty($primaryKey)) |
||
| 350 | { |
||
| 351 | $columnFound = true; |
||
| 352 | } |
||
| 353 | |||
| 354 | if (in_array($groupColumnsKey, array('FROM'))) |
||
| 355 | { |
||
| 356 | if (empty($primaryKey) && $groupColumnsKey != 'FROM') |
||
| 357 | { |
||
| 358 | $tagColumnsValue['base_expr'] = self::breakColumnAndReplace($tagColumnsValue['base_expr'], $column['table']['alias']['name']); |
||
| 359 | } |
||
| 360 | else |
||
| 361 | { |
||
| 362 | $tagColumnsValue['base_expr'] = self::breakColumnAndReplace($tagColumnsValue['base_expr'], $column['table']['alias']['originalName']); |
||
| 363 | } |
||
| 364 | } |
||
| 365 | else |
||
| 366 | { |
||
| 367 | if (in_array($groupColumnsKey, array('ORDER', 'WHERE', 'GROUP')) && !empty($primaryKey)) |
||
| 368 | { |
||
| 369 | $tagColumnsValue['base_expr'] = self::breakColumnAndReplace($tagColumnsValue['base_expr'], $column['table']['alias']['originalName']); |
||
| 370 | } |
||
| 371 | else |
||
| 372 | { |
||
| 373 | $tagColumnsValue['base_expr'] = $column['base_expr']; |
||
| 374 | |||
| 375 | if ($addAlias |
||
| 376 | && !empty($column['alias']) |
||
| 377 | && !in_array($groupColumnsKey, array('ORDER', 'WHERE', 'GROUP'))) |
||
| 378 | { |
||
| 379 | $alias = $column['alias']; |
||
| 380 | |||
| 381 | if (!empty($tagColumnsValue['alias']['name'])) |
||
| 382 | { |
||
| 383 | $alias = $tagColumnsValue['alias']['name']; |
||
| 384 | } |
||
| 385 | |||
| 386 | $alias = $db->qn(self::cleanEscaping($alias)); |
||
| 387 | $tagColumnsValue['alias'] = array( |
||
| 388 | 'as' => true, |
||
| 389 | 'name' => $alias, |
||
| 390 | 'base_expr' => 'as ' . $alias |
||
| 391 | ); |
||
| 392 | } |
||
| 393 | } |
||
| 394 | } |
||
| 395 | } |
||
| 396 | } |
||
| 397 | elseif (!empty($tagColumnsValue['sub_tree'])) |
||
| 398 | { |
||
| 399 | if (!empty($tagColumnsValue['expr_type']) && $tagColumnsValue['expr_type'] == 'subquery') |
||
| 400 | { |
||
| 401 | // SubQuery is already parsed so we do not need to parse columns again |
||
| 402 | } |
||
| 403 | elseif (!empty($tagColumnsValue['expr_type']) && in_array($tagColumnsValue['expr_type'], array('expression'))) |
||
| 404 | { |
||
| 405 | foreach ($tagColumnsValue['sub_tree'] as $subKey => $subTree) |
||
| 406 | { |
||
| 407 | if (!empty($tagColumnsValue['sub_tree'][$subKey]['sub_tree'])) |
||
| 408 | { |
||
| 409 | $tagColumnsValue['sub_tree'][$subKey]['sub_tree'] = self::parseColumnReplacements( |
||
| 410 | array($groupColumnsKey => $tagColumnsValue['sub_tree'][$subKey]['sub_tree']), |
||
| 411 | $columns, |
||
| 412 | $translationTables, |
||
| 413 | $columnFound, |
||
| 414 | false |
||
| 415 | ); |
||
| 416 | $tagColumnsValue['sub_tree'][$subKey]['sub_tree'] = $tagColumnsValue['sub_tree'][$subKey]['sub_tree'][$groupColumnsKey]; |
||
| 417 | } |
||
| 418 | } |
||
| 419 | } |
||
| 420 | elseif (is_array($tagColumnsValue['sub_tree'])) |
||
| 421 | { |
||
| 422 | // We will not replace some aggregate functions columns |
||
| 423 | if (!(in_array($tagColumnsValue['expr_type'], array('aggregate_function')) && strtolower($tagColumnsValue['base_expr']) == 'count')) |
||
| 424 | { |
||
| 425 | $keys = array_keys($tagColumnsValue['sub_tree']); |
||
| 426 | |||
| 427 | if (!is_numeric($keys[0])) |
||
| 428 | { |
||
| 429 | $tagColumnsValue['sub_tree'] = self::parseColumnReplacements( |
||
| 430 | $tagColumnsValue['sub_tree'], |
||
| 431 | $columns, |
||
| 432 | $translationTables, |
||
| 433 | $columnFound, |
||
| 434 | false |
||
| 435 | ); |
||
| 436 | } |
||
| 437 | else |
||
| 438 | { |
||
| 439 | $tagColumnsValue['sub_tree'] = self::parseColumnReplacements( |
||
| 440 | array($groupColumnsKey => $tagColumnsValue['sub_tree']), |
||
| 441 | $columns, |
||
| 442 | $translationTables, |
||
| 443 | $columnFound, |
||
| 444 | false |
||
| 445 | ); |
||
| 446 | $tagColumnsValue['sub_tree'] = $tagColumnsValue['sub_tree'][$groupColumnsKey]; |
||
| 447 | } |
||
| 448 | } |
||
| 449 | } |
||
| 450 | } |
||
| 451 | elseif (!empty($tagColumnsValue['ref_clause'])) |
||
| 452 | { |
||
| 453 | if (is_array($tagColumnsValue['ref_clause'])) |
||
| 454 | { |
||
| 455 | $keys = array_keys($tagColumnsValue['ref_clause']); |
||
| 456 | |||
| 457 | if (!is_numeric($keys[0])) |
||
| 458 | { |
||
| 459 | $tagColumnsValue['ref_clause'] = self::parseColumnReplacements( |
||
| 460 | $tagColumnsValue['ref_clause'], |
||
| 461 | $columns, |
||
| 462 | $translationTables, |
||
| 463 | $columnFound, |
||
| 464 | false |
||
| 465 | ); |
||
| 466 | } |
||
| 467 | else |
||
| 468 | { |
||
| 469 | $tagColumnsValue['ref_clause'] = self::parseColumnReplacements( |
||
| 470 | array($groupColumnsKey => $tagColumnsValue['ref_clause']), |
||
| 471 | $columns, |
||
| 472 | $translationTables, |
||
| 473 | $columnFound, |
||
| 474 | false |
||
| 475 | ); |
||
| 476 | $tagColumnsValue['ref_clause'] = $tagColumnsValue['ref_clause'][$groupColumnsKey]; |
||
| 477 | } |
||
| 478 | } |
||
| 479 | } |
||
| 480 | |||
| 481 | if (!is_numeric($tagKey)) |
||
| 482 | { |
||
| 483 | $filteredGroup[$tagKey] = $tagColumnsValue; |
||
| 484 | } |
||
| 485 | else |
||
| 486 | { |
||
| 487 | $filteredGroup[] = $tagColumnsValue; |
||
| 488 | } |
||
| 489 | } |
||
| 490 | |||
| 491 | $parsedSqlColumns[$groupColumnsKey] = $filteredGroup; |
||
| 492 | } |
||
| 493 | } |
||
| 494 | } |
||
| 495 | |||
| 496 | return $parsedSqlColumns; |
||
| 497 | } |
||
| 498 | |||
| 499 | /** |
||
| 500 | * Recursive method which go through every array and joins table if we have found the match |
||
| 501 | * |
||
| 502 | * @param array $parsedSql Parsed SQL in array format |
||
| 503 | * @param array $translationTables List of translation tables |
||
| 504 | * @param array &$foundTables Found replacement tables |
||
| 505 | * @param array &$originalTables Found original tables used for creating unique alias |
||
| 506 | * @param string $language Language tag you want to fetch translation from |
||
| 507 | * @param string &$subQueryFound If sub query is found then we must parse end sql |
||
| 508 | * |
||
| 509 | * @return array Parsed query with added table joins if found |
||
| 510 | */ |
||
| 511 | public static function parseTableReplacements($parsedSql, $translationTables, &$foundTables, &$originalTables, $language, &$subQueryFound) |
||
| 512 | { |
||
| 513 | if (!empty($parsedSql) && is_array($parsedSql)) |
||
| 514 | { |
||
| 515 | // Replace all Tables and keys |
||
| 516 | foreach ($parsedSql as $groupKey => $parsedGroup) |
||
| 517 | { |
||
| 518 | if (!empty($parsedGroup)) |
||
| 519 | { |
||
| 520 | $filteredGroup = array(); |
||
| 521 | $filteredGroupEndPosition = array(); |
||
| 522 | |||
| 523 | foreach ($parsedGroup as $tagKey => $tagValue) |
||
| 524 | { |
||
| 525 | $tableName = null; |
||
| 526 | $newTagValue = null; |
||
| 527 | |||
| 528 | if (!empty($tagValue['expr_type']) && $tagValue['expr_type'] == 'table' && !empty($tagValue['table'])) |
||
| 529 | { |
||
| 530 | $tableName = self::getNameIfIncluded( |
||
| 531 | $tagValue['table'], |
||
| 532 | !empty($tagValue['alias']['name']) ? $tagValue['alias']['name'] : '', |
||
| 533 | $translationTables, |
||
| 534 | true, |
||
| 535 | $groupKey |
||
| 536 | ); |
||
| 537 | |||
| 538 | if (!empty($tableName)) |
||
| 539 | { |
||
| 540 | $newTagValue = $tagValue; |
||
| 541 | $newTagValue['originalTableName'] = $tableName; |
||
| 542 | $newTagValue['table'] = RTranslationTable::getTranslationsTableName($tableName, ''); |
||
| 543 | $newTagValue['join_type'] = 'LEFT'; |
||
| 544 | $newTagValue['ref_type'] = 'ON'; |
||
| 545 | $alias = self::getUniqueAlias($tableName, $originalTables); |
||
| 546 | |||
| 547 | if (!empty($newTagValue['alias']['name'])) |
||
| 548 | { |
||
| 549 | $alias = $newTagValue['alias']['name']; |
||
| 550 | } |
||
| 551 | |||
| 552 | $tagValue['alias'] = array( |
||
| 553 | 'as' => true, |
||
| 554 | 'name' => $alias, |
||
| 555 | 'base_expr' => '' |
||
| 556 | ); |
||
| 557 | |||
| 558 | $newTagValue['alias'] = array( |
||
| 559 | 'as' => true, |
||
| 560 | 'name' => self::getUniqueAlias($newTagValue['table'], $foundTables), |
||
| 561 | 'originalName' => $alias, |
||
| 562 | 'base_expr' => '' |
||
| 563 | ); |
||
| 564 | |||
| 565 | $refClause = self::createParserJoinOperand( |
||
| 566 | $newTagValue['alias']['name'], |
||
| 567 | '=', |
||
| 568 | $newTagValue['alias']['originalName'], |
||
| 569 | $translationTables[$tableName], |
||
| 570 | $language |
||
| 571 | ); |
||
| 572 | $newTagValue['ref_clause'] = $refClause; |
||
| 573 | $newTagValue['index_hints'] = false; |
||
| 574 | $foundTables[] = $newTagValue; |
||
| 575 | $originalTables[$newTagValue['alias']['originalName']] = isset($originalTables[$newTagValue['alias']['originalName']]) ? |
||
| 576 | $originalTables[$newTagValue['alias']['originalName']]++ : 1; |
||
| 577 | } |
||
| 578 | } |
||
| 579 | // There is an issue in sql parser for UNION and UNION ALL, this is a solution for it |
||
| 580 | elseif (!empty($tagValue['union_tree']) && is_array($tagValue['union_tree']) && in_array('UNION', $tagValue['union_tree'])) |
||
| 581 | { |
||
| 582 | $subQueryFound = true; |
||
| 583 | $unionTree = array(); |
||
| 584 | |||
| 585 | foreach ($tagValue['union_tree'] as $union) |
||
| 586 | { |
||
| 587 | $union = trim($union); |
||
| 588 | |||
| 589 | if (!empty($union) && strtoupper($union) != 'UNION') |
||
| 590 | { |
||
| 591 | $parsedSubQuery = self::buildTranslationQuery(self::removeParenthesisFromStart($union)); |
||
| 592 | $unionTree[] = !empty($parsedSubQuery) ? '(' . $parsedSubQuery . ')' : $union; |
||
| 593 | } |
||
| 594 | } |
||
| 595 | |||
| 596 | $tagValue['base_expr'] = '(' . implode(' UNION ', $unionTree) . ')'; |
||
| 597 | $tagValue['expr_type'] = 'const'; |
||
| 598 | |||
| 599 | if (!empty($tagValue['sub_tree'])) |
||
| 600 | { |
||
| 601 | unset($tagValue['sub_tree']); |
||
| 602 | } |
||
| 603 | |||
| 604 | if (!empty($tagValue['join_type'])) |
||
| 605 | { |
||
| 606 | unset($tagValue['join_type']); |
||
| 607 | } |
||
| 608 | } |
||
| 609 | // Other types of expressions |
||
| 610 | elseif (!empty($tagValue['sub_tree'])) |
||
| 611 | { |
||
| 612 | if (!empty($tagValue['expr_type']) && $tagValue['expr_type'] == 'subquery') |
||
| 613 | { |
||
| 614 | $parsedSubQuery = self::buildTranslationQuery($tagValue['base_expr']); |
||
| 615 | |||
| 616 | if (!empty($parsedSubQuery)) |
||
| 617 | { |
||
| 618 | $sqlParser = new RDatabaseSqlparserSqlparser($parsedSubQuery); |
||
| 619 | $tagValue['sub_tree'] = $sqlParser->parsed; |
||
| 620 | $tagValue['base_expr'] = $parsedSubQuery; |
||
| 621 | $subQueryFound = true; |
||
| 622 | } |
||
| 623 | } |
||
| 624 | elseif (!empty($tagValue['expr_type']) && in_array($tagValue['expr_type'], array('expression'))) |
||
| 625 | { |
||
| 626 | foreach ($tagValue['sub_tree'] as $subKey => $subTree) |
||
| 627 | { |
||
| 628 | // In case we have a Subquery directly under the expression we handle it separately |
||
| 629 | if (!empty($subTree['expr_type']) && $subTree['expr_type'] == 'subquery') |
||
| 630 | { |
||
| 631 | // We need to remove brackets from the query or else the query will not be parsed properly |
||
| 632 | $sqlBracketLess = self::removeParenthesisFromStart($subTree['base_expr']); |
||
| 633 | $parsedSubQuery = self::buildTranslationQuery($sqlBracketLess); |
||
| 634 | |||
| 635 | if (!empty($parsedSubQuery)) |
||
| 636 | { |
||
| 637 | $sqlParser = new RDatabaseSqlparserSqlparser($parsedSubQuery); |
||
| 638 | $tagValue['sub_tree'][$subKey]['sub_tree'] = $sqlParser->parsed; |
||
| 639 | $tagValue['sub_tree'][$subKey]['base_expr'] = '(' . $parsedSubQuery . ')'; |
||
| 640 | $subQueryFound = true; |
||
| 641 | } |
||
| 642 | } |
||
| 643 | elseif (!empty($tagValue['sub_tree'][$subKey]['sub_tree'])) |
||
| 644 | { |
||
| 645 | $tagValue['sub_tree'][$subKey]['sub_tree'] = self::parseTableReplacements( |
||
| 646 | $tagValue['sub_tree'][$subKey]['sub_tree'], |
||
| 647 | $translationTables, |
||
| 648 | $foundTables, |
||
| 649 | $originalTables, |
||
| 650 | $language, |
||
| 651 | $subQueryFound |
||
| 652 | ); |
||
| 653 | } |
||
| 654 | } |
||
| 655 | } |
||
| 656 | else |
||
| 657 | { |
||
| 658 | $tagValue['sub_tree'] = self::parseTableReplacements( |
||
| 659 | $tagValue['sub_tree'], |
||
| 660 | $translationTables, |
||
| 661 | $foundTables, |
||
| 662 | $originalTables, |
||
| 663 | $language, |
||
| 664 | $subQueryFound |
||
| 665 | ); |
||
| 666 | } |
||
| 667 | } |
||
| 668 | |||
| 669 | if (!is_numeric($tagKey)) |
||
| 670 | { |
||
| 671 | $filteredGroup[$tagKey] = $tagValue; |
||
| 672 | } |
||
| 673 | else |
||
| 674 | { |
||
| 675 | $filteredGroup[] = $tagValue; |
||
| 676 | } |
||
| 677 | |||
| 678 | if (!empty($newTagValue)) |
||
| 679 | { |
||
| 680 | if (!empty($translationTables[$tableName]->tableJoinEndPosition)) |
||
| 681 | { |
||
| 682 | $filteredGroupEndPosition[] = $newTagValue; |
||
| 683 | } |
||
| 684 | else |
||
| 685 | { |
||
| 686 | $filteredGroup[] = $newTagValue; |
||
| 687 | } |
||
| 688 | } |
||
| 689 | } |
||
| 690 | |||
| 691 | foreach ($filteredGroupEndPosition as $table) |
||
| 692 | { |
||
| 693 | $filteredGroup[] = $table; |
||
| 694 | } |
||
| 695 | |||
| 696 | $parsedSql[$groupKey] = $filteredGroup; |
||
| 697 | } |
||
| 698 | } |
||
| 699 | } |
||
| 700 | |||
| 701 | return $parsedSql; |
||
| 702 | } |
||
| 703 | |||
| 704 | /** |
||
| 705 | * Creates unique Alias name not used in existing query |
||
| 706 | * |
||
| 707 | * @param string $originalTableName Original table name which we use for creating alias |
||
| 708 | * @param array $foundTables Currently used tables in the query |
||
| 709 | * @param int $counter Auto increasing number if we already have alias with the same name |
||
| 710 | * |
||
| 711 | * @return string Parsed query with added table joins and fields if found |
||
| 712 | */ |
||
| 713 | public static function getUniqueAlias($originalTableName, $foundTables = array(), $counter = 0) |
||
| 714 | { |
||
| 715 | $string = str_replace('#__', '', $originalTableName); |
||
| 716 | $string .= '_' . substr(RFilesystemFile::getUniqueName($counter), 0, 4); |
||
| 717 | |||
| 718 | foreach ($foundTables as $foundTable) |
||
| 719 | { |
||
| 720 | if (isset($foundTable['alias']['name']) && $foundTable['alias']['name'] == $string) |
||
| 721 | { |
||
| 722 | $counter++; |
||
| 723 | |||
| 724 | return self::getUniqueAlias($originalTableName, $foundTables, $counter); |
||
| 725 | } |
||
| 726 | } |
||
| 727 | |||
| 728 | return $string; |
||
| 729 | } |
||
| 730 | |||
| 731 | /** |
||
| 732 | * Breaks column name and replaces alias with the new one |
||
| 733 | * |
||
| 734 | * @param string $column Column Name with or without prefix |
||
| 735 | * @param string $replaceWith Alias name to replace current one |
||
| 736 | * |
||
| 737 | * @return string Parsed query with added table joins and fields if found |
||
| 738 | */ |
||
| 739 | public static function breakColumnAndReplace($column, $replaceWith) |
||
| 740 | { |
||
| 741 | $column = explode('.', $column); |
||
| 742 | |||
| 743 | if (!empty($column)) |
||
| 744 | { |
||
| 745 | if (count($column) == 1) |
||
| 746 | { |
||
| 747 | $column[1] = $column[0]; |
||
| 748 | } |
||
| 749 | |||
| 750 | if (empty($replaceWith)) |
||
| 751 | { |
||
| 752 | return $column[1]; |
||
| 753 | } |
||
| 754 | |||
| 755 | $column[0] = $replaceWith; |
||
| 756 | } |
||
| 757 | |||
| 758 | return implode('.', $column); |
||
| 759 | } |
||
| 760 | |||
| 761 | /** |
||
| 762 | * Creates array in sql Parser format, this function adds language filter as well |
||
| 763 | * |
||
| 764 | * @param string $newTable Table alias of new table |
||
| 765 | * @param string $operator Operator of joining tables |
||
| 766 | * @param string $oldTable Alias of original table |
||
| 767 | * @param object $tableObject Alias of original table |
||
| 768 | * @param string $language Language tag you want to fetch translation from |
||
| 769 | * |
||
| 770 | * @return string Parsed query with added table joins and fields if found |
||
| 771 | */ |
||
| 772 | public static function createParserJoinOperand($newTable, $operator, $oldTable, $tableObject, $language) |
||
| 773 | { |
||
| 774 | $db = JFactory::getDbo(); |
||
| 775 | $refClause = array(); |
||
| 776 | |||
| 777 | if (!empty($tableObject->primaryKeys)) |
||
| 778 | { |
||
| 779 | foreach ($tableObject->primaryKeys as $primaryKey) |
||
| 780 | { |
||
| 781 | $refClause[] = self::createParserElement('colref', $db->qn($newTable) . '.' . $primaryKey); |
||
| 782 | $refClause[] = self::createParserElement('operator', $operator); |
||
| 783 | $refClause[] = self::createParserElement('colref', $db->qn(self::cleanEscaping($oldTable)) . '.' . $primaryKey); |
||
| 784 | |||
| 785 | $refClause[] = self::createParserElement('operator', 'AND'); |
||
| 786 | } |
||
| 787 | } |
||
| 788 | |||
| 789 | $refClause[] = self::createParserElement('colref', $db->qn($newTable) . '.rctranslations_language'); |
||
| 790 | $refClause[] = self::createParserElement('operator', '='); |
||
| 791 | $refClause[] = self::createParserElement('colref', $db->q($language)); |
||
| 792 | |||
| 793 | $refClause[] = self::createParserElement('operator', 'AND'); |
||
| 794 | |||
| 795 | $refClause[] = self::createParserElement('colref', $db->qn($newTable) . '.rctranslations_state'); |
||
| 796 | $refClause[] = self::createParserElement('operator', '='); |
||
| 797 | $refClause[] = self::createParserElement('colref', $db->q('1')); |
||
| 798 | |||
| 799 | if (!empty($tableObject->tableJoinParams)) |
||
| 800 | { |
||
| 801 | foreach ($tableObject->tableJoinParams as $join) |
||
| 802 | { |
||
| 803 | $leftSide = $join['left']; |
||
| 804 | $rightSide = $join['right']; |
||
| 805 | |||
| 806 | // Add alias if needed to the left side |
||
| 807 | if (!empty($join['aliasLeft'])) |
||
| 808 | { |
||
| 809 | $leftSide = ($join['aliasLeft'] == 'original' ? $db->qn(self::cleanEscaping($oldTable)) : $db->qn($newTable)) . '.' . $leftSide; |
||
| 810 | } |
||
| 811 | |||
| 812 | // Add alias if needed to the right side |
||
| 813 | if (!empty($join['aliasRight'])) |
||
| 814 | { |
||
| 815 | $rightSide = ($join['aliasRight'] == 'original' ? $db->qn(self::cleanEscaping($oldTable)) : $db->qn($newTable)) . '.' . $rightSide; |
||
| 816 | } |
||
| 817 | |||
| 818 | $refClause[] = self::createParserElement('operator', $join['expressionOperator']); |
||
| 819 | $refClause[] = self::createParserElement('colref', $leftSide); |
||
| 820 | $refClause[] = self::createParserElement('operator', $join['operator']); |
||
| 821 | $refClause[] = self::createParserElement('colref', $rightSide); |
||
| 822 | } |
||
| 823 | } |
||
| 824 | |||
| 825 | return $refClause; |
||
| 826 | } |
||
| 827 | |||
| 828 | /** |
||
| 829 | * Create Table Join Parameter |
||
| 830 | * |
||
| 831 | * @param string $left Table alias of new table |
||
| 832 | * @param string $operator Operator of joining tables |
||
| 833 | * @param string $right Alias of original table |
||
| 834 | * @param object $aliasLeft Alias of original table |
||
| 835 | * @param string $aliasRight Language tag you want to fetch translation from |
||
| 836 | * @param string $expressionOperator Language tag you want to fetch translation from |
||
| 837 | * |
||
| 838 | * @return array table join param |
||
| 839 | */ |
||
| 840 | public static function createTableJoinParam($left, $operator = '=', $right = '', $aliasLeft = null, $aliasRight = null, $expressionOperator = 'AND') |
||
| 841 | { |
||
| 842 | return array( |
||
| 843 | 'left' => $left, |
||
| 844 | 'operator' => $operator, |
||
| 845 | 'right' => $right, |
||
| 846 | 'aliasLeft' => $aliasLeft, |
||
| 847 | 'aliasRight' => $aliasRight, |
||
| 848 | 'expressionOperator' => $expressionOperator, |
||
| 849 | ); |
||
| 850 | } |
||
| 851 | |||
| 852 | /** |
||
| 853 | * Create Table Join Parameter |
||
| 854 | * |
||
| 855 | * @param array $originalTableColumns Table alias of new table |
||
| 856 | * @param array $tableColumns Operator of joining tables |
||
| 857 | * @param string $alias Original table alias |
||
| 858 | * |
||
| 859 | * @return array table join param |
||
| 860 | */ |
||
| 861 | public static function addBaseColumns($originalTableColumns, $tableColumns, $alias) |
||
| 862 | { |
||
| 863 | $columns = array(); |
||
| 864 | |||
| 865 | foreach ($originalTableColumns as $key => $value) |
||
| 866 | { |
||
| 867 | if (!in_array($key, $tableColumns)) |
||
| 868 | { |
||
| 869 | $columns[] = $alias . '.' . $key; |
||
| 870 | } |
||
| 871 | } |
||
| 872 | |||
| 873 | return implode(',', $columns); |
||
| 874 | } |
||
| 875 | |||
| 876 | /** |
||
| 877 | * Creates array in sql Parser format, this function adds language filter as well |
||
| 878 | * |
||
| 879 | * @param string $exprType Expression type |
||
| 880 | * @param string $baseExpr Base expression |
||
| 881 | * @param bool $subTree Sub Tree |
||
| 882 | * |
||
| 883 | * @return array Parser Element in array format |
||
| 884 | */ |
||
| 885 | public static function createParserElement($exprType, $baseExpr, $subTree = false) |
||
| 886 | { |
||
| 887 | $element = array( |
||
| 888 | 'expr_type' => $exprType, |
||
| 889 | 'base_expr' => $baseExpr, |
||
| 890 | 'sub_tree' => $subTree |
||
| 891 | ); |
||
| 892 | |||
| 893 | return $element; |
||
| 894 | } |
||
| 895 | |||
| 896 | /** |
||
| 897 | * Check for different types of field usage in field list and returns name with alias if present |
||
| 898 | * |
||
| 899 | * @param string $field Field name this can be with or without quotes |
||
| 900 | * @param string $tableAlias Table alias | optional |
||
| 901 | * @param array $fieldList List of fields to check against |
||
| 902 | * @param bool $isTable If we are checking against table string |
||
| 903 | * @param string $groupName Group name |
||
| 904 | * |
||
| 905 | * @return mixed Returns List item if Field name is included in field list |
||
| 906 | */ |
||
| 907 | public static function getNameIfIncluded($field, $tableAlias = '', $fieldList = array(), $isTable = false, $groupName = 'SELECT') |
||
| 908 | { |
||
| 909 | // No fields to search for |
||
| 910 | if (empty($fieldList) || empty($field) || self::skipTranslationColumn($groupName, $field)) |
||
| 911 | { |
||
| 912 | return ''; |
||
| 913 | } |
||
| 914 | |||
| 915 | $field = self::cleanEscaping($field); |
||
| 916 | $fieldParts = explode('.', $field); |
||
| 917 | $alias = ''; |
||
| 918 | |||
| 919 | if (count($fieldParts) > 1) |
||
| 920 | { |
||
| 921 | $alias = $fieldParts[0]; |
||
| 922 | $field = $fieldParts[1]; |
||
| 923 | } |
||
| 924 | |||
| 925 | // Check for field inclusion with various cases |
||
| 926 | foreach ($fieldList as $fieldFromListQuotes => $fieldFromList) |
||
| 927 | { |
||
| 928 | if ($isTable) |
||
| 929 | { |
||
| 930 | switch (self::cleanEscaping($fieldFromListQuotes)) |
||
| 931 | { |
||
| 932 | case $field: |
||
| 933 | if (!empty($fieldFromList->tableAliasesToParse) |
||
| 934 | && !empty($tableAlias) |
||
| 935 | && !in_array(self::cleanEscaping($tableAlias), $fieldFromList->tableAliasesToParse)) |
||
| 936 | { |
||
| 937 | continue 2; |
||
| 938 | } |
||
| 939 | |||
| 940 | return $fieldFromListQuotes; |
||
| 941 | } |
||
| 942 | } |
||
| 943 | elseif ($tableAlias == '') |
||
| 944 | { |
||
| 945 | switch (self::cleanEscaping($fieldFromList['columnName'])) |
||
| 946 | { |
||
| 947 | case $field: |
||
| 948 | case self::cleanEscaping($fieldFromList['table']['alias']['originalName'] . '.' . $field): |
||
| 949 | // If this is different table we do not check columns |
||
| 950 | if (!empty($alias) && $alias != self::cleanEscaping($fieldFromList['table']['alias']['originalName'])) |
||
| 951 | { |
||
| 952 | continue 2; |
||
| 953 | } |
||
| 954 | |||
| 955 | return $fieldFromList; |
||
| 956 | } |
||
| 957 | } |
||
| 958 | else |
||
| 959 | { |
||
| 960 | switch (self::cleanEscaping($fieldFromList)) |
||
| 961 | { |
||
| 962 | case $field: |
||
| 963 | case self::cleanEscaping($tableAlias . '.' . $field): |
||
| 964 | |||
| 965 | return $fieldFromList; |
||
| 966 | } |
||
| 967 | } |
||
| 968 | } |
||
| 969 | |||
| 970 | return ''; |
||
| 971 | } |
||
| 972 | |||
| 973 | /** |
||
| 974 | * Check for database escape and remove it |
||
| 975 | * |
||
| 976 | * @param string $sql Sql to check against |
||
| 977 | * |
||
| 978 | * @return string Returns true if Field name is included in field list |
||
| 979 | */ |
||
| 980 | public static function cleanEscaping($sql) |
||
| 981 | { |
||
| 982 | return str_replace('`', '', trim($sql)); |
||
| 983 | } |
||
| 984 | |||
| 985 | /** |
||
| 986 | * Check for enclosing brackets and remove it |
||
| 987 | * |
||
| 988 | * @param string $sql Sql to check against |
||
| 989 | * |
||
| 990 | * @return string Returns sql query without enclosing brackets |
||
| 991 | */ |
||
| 992 | public static function removeParenthesisFromStart($sql) |
||
| 1044 | } |
||
| 1045 | |||
| 1046 | /** |
||
| 1047 | * Check for database escape and remove it |
||
| 1048 | * |
||
| 1049 | * @param string $groupName Group name |
||
| 1050 | * @param string $field Field name this can be with or without quotes |
||
| 1051 | * |
||
| 1052 | * @return bool Returns true if Field name is included in field list |
||
| 1053 | */ |
||
| 1054 | public static function skipTranslationColumn($groupName, $field) |
||
| 1055 | { |
||
| 1056 | $db = JFactory::getDbo(); |
||
| 1057 | |||
| 1058 | if (!empty($db->skipColumns)) |
||
| 1059 | { |
||
| 1060 | foreach ($db->skipColumns as $skipGroupName => $skipColumns) |
||
| 1061 | { |
||
| 1062 | if (!empty($skipColumns)) |
||
| 1063 | { |
||
| 1064 | foreach ($skipColumns as $column) |
||
| 1065 | { |
||
| 1066 | if ($groupName == $skipGroupName && self::cleanEscaping($field) == $column) |
||
| 1067 | { |
||
| 1068 | return true; |
||
| 1069 | } |
||
| 1070 | } |
||
| 1071 | } |
||
| 1072 | } |
||
| 1073 | } |
||
| 1074 | |||
| 1075 | return false; |
||
| 1076 | } |
||
| 1077 | |||
| 1078 | /** |
||
| 1079 | * Set a translation option value. |
||
| 1080 | * |
||
| 1081 | * @param string $key The key |
||
| 1082 | * @param mixed $val The default value |
||
| 1083 | * |
||
| 1084 | * @return null |
||
| 1085 | */ |
||
| 1086 | public static function setOption($key, $val) |
||
| 1087 | { |
||
| 1088 | self::$options[$key] = $val; |
||
| 1089 | } |
||
| 1090 | |||
| 1091 | /** |
||
| 1092 | * Get a translation option value. |
||
| 1093 | * |
||
| 1094 | * @param string $key The key |
||
| 1095 | * @param mixed $default The default value |
||
| 1096 | * |
||
| 1097 | * @return mixed The value or the default value |
||
| 1098 | */ |
||
| 1099 | public static function getOption($key, $default = null) |
||
| 1100 | { |
||
| 1101 | if (isset(self::$options[$key])) |
||
| 1102 | { |
||
| 1103 | return self::$options[$key]; |
||
| 1104 | } |
||
| 1105 | |||
| 1106 | return $default; |
||
| 1107 | } |
||
| 1108 | |||
| 1109 | /** |
||
| 1110 | * Set a translation option fallback value. |
||
| 1111 | * |
||
| 1112 | * @param bool $enable Enable or disable translation fallback feature |
||
| 1113 | * |
||
| 1114 | * @return null |
||
| 1115 | */ |
||
| 1116 | public static function setTranslationFallback($enable = true) |
||
| 1117 | { |
||
| 1118 | self::setOption('translationFallback', $enable); |
||
| 1119 | } |
||
| 1120 | |||
| 1121 | /** |
||
| 1122 | * Set a translation option force translate default value. |
||
| 1123 | * |
||
| 1124 | * @param bool $enable Enable or disable force translate default language feature |
||
| 1125 | * |
||
| 1126 | * @return null |
||
| 1127 | */ |
||
| 1128 | public static function setForceTranslateDefaultLanguage($enable = false) |
||
| 1131 | } |
||
| 1132 | |||
| 1133 | /** |
||
| 1134 | * Set a translate data in Admin value. |
||
| 1135 | * |
||
| 1136 | * @param bool $enable Enable or disable translation fallback feature |
||
| 1137 | * |
||
| 1138 | * @return null |
||
| 1139 | */ |
||
| 1140 | public static function setTranslationInAdmin($enable = false) |
||
| 1143 | } |
||
| 1144 | } |
||
| 1145 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.