Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like PricePNRWithBookingClass13 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
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 PricePNRWithBookingClass13, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 57 | class PricePNRWithBookingClass13 extends BaseWsMessage |
||
| 58 | { |
||
| 59 | /** |
||
| 60 | * @var PricePnr13\PricingOptionGroup[] |
||
| 61 | */ |
||
| 62 | public $pricingOptionGroup = []; |
||
| 63 | |||
| 64 | /** |
||
| 65 | * PricePNRWithBookingClass13 constructor. |
||
| 66 | * |
||
| 67 | * @param FarePricePnrWithBookingClassOptions|LowerFareOpt|LowestFareOpt|null $options |
||
| 68 | * @throws MessageVersionUnsupportedException |
||
| 69 | */ |
||
| 70 | public function __construct($options) |
||
| 71 | { |
||
| 72 | if (!is_null($options)) { |
||
| 73 | $this->pricingOptionGroup = $this->loadPricingOptionsFromRequestOptions($options); |
||
| 74 | } |
||
| 75 | } |
||
| 76 | |||
| 77 | /** |
||
| 78 | * Load an array of PricingOptionGroup objects from the Pricing request options. |
||
| 79 | * |
||
| 80 | * Extracted because this method is also used in the InformativePricingWithoutPnr messages. |
||
| 81 | * |
||
| 82 | * @param FarePricePnrWithBookingClassOptions|LowerFareOpt|LowestFareOpt $options |
||
| 83 | * @return PricingOptionGroup[] |
||
| 84 | */ |
||
| 85 | public static function loadPricingOptionsFromRequestOptions($options) |
||
| 86 | { |
||
| 87 | $priceOptions = []; |
||
| 88 | |||
| 89 | $priceOptions = self::mergeOptions( |
||
| 90 | $priceOptions, |
||
| 91 | self::makePricingOptionForValidatingCarrier($options->validatingCarrier) |
||
| 92 | ); |
||
| 93 | |||
| 94 | $priceOptions = self::mergeOptions( |
||
| 95 | $priceOptions, |
||
| 96 | self::makePricingOptionForCurrencyOverride($options->currencyOverride) |
||
| 97 | ); |
||
| 98 | |||
| 99 | $priceOptions = self::mergeOptions( |
||
| 100 | $priceOptions, |
||
| 101 | self::makePricingOptionFareBasisOverride($options->pricingsFareBasis) |
||
| 102 | ); |
||
| 103 | |||
| 104 | $priceOptions = self::mergeOptions( |
||
| 105 | $priceOptions, |
||
| 106 | self::makeOverrideOptions($options->overrideOptions, $priceOptions) |
||
| 107 | ); |
||
| 108 | |||
| 109 | $priceOptions = self::mergeOptions( |
||
| 110 | $priceOptions, |
||
| 111 | self::loadCorpNegoFare($options->corporateNegoFare) |
||
| 112 | ); |
||
| 113 | |||
| 114 | $priceOptions = self::mergeOptions( |
||
| 115 | $priceOptions, |
||
| 116 | self::loadCorpUniFares($options->corporateUniFares, $options->awardPricing) |
||
| 117 | ); |
||
| 118 | |||
| 119 | $priceOptions = self::mergeOptions( |
||
| 120 | $priceOptions, |
||
| 121 | self::loadObFees($options->obFees, $options->obFeeRefs) |
||
| 122 | ); |
||
| 123 | |||
| 124 | $priceOptions = self::mergeOptions( |
||
| 125 | $priceOptions, |
||
| 126 | self::loadPaxDiscount($options->paxDiscountCodes, $options->paxDiscountCodeRefs) |
||
| 127 | ); |
||
| 128 | |||
| 129 | $priceOptions = self::mergeOptions( |
||
| 130 | $priceOptions, |
||
| 131 | self::loadPointOverrides( |
||
| 132 | $options->pointOfSaleOverride, |
||
| 133 | $options->pointOfTicketingOverride |
||
| 134 | ) |
||
| 135 | ); |
||
| 136 | |||
| 137 | $priceOptions = self::mergeOptions( |
||
| 138 | $priceOptions, |
||
| 139 | self::loadPricingLogic($options->pricingLogic) |
||
| 140 | ); |
||
| 141 | |||
| 142 | $priceOptions = self::mergeOptions( |
||
| 143 | $priceOptions, |
||
| 144 | self::loadTicketType($options->ticketType) |
||
| 145 | ); |
||
| 146 | |||
| 147 | $priceOptions = self::mergeOptions( |
||
| 148 | $priceOptions, |
||
| 149 | self::loadTaxes($options->taxes) |
||
| 150 | ); |
||
| 151 | |||
| 152 | $priceOptions = self::mergeOptions( |
||
| 153 | $priceOptions, |
||
| 154 | self::loadExemptTaxes($options->exemptTaxes) |
||
| 155 | ); |
||
| 156 | |||
| 157 | $priceOptions = self::mergeOptions( |
||
| 158 | $priceOptions, |
||
| 159 | self::loadPastDate($options->pastDatePricing) |
||
| 160 | ); |
||
| 161 | |||
| 162 | $priceOptions = self::mergeOptions( |
||
| 163 | $priceOptions, |
||
| 164 | self::loadReferences($options->references) |
||
| 165 | ); |
||
| 166 | |||
| 167 | // All options processed, no options found: |
||
| 168 | if (empty($priceOptions)) { |
||
| 169 | $priceOptions[] = new PricingOptionGroup(PricingOptionKey::OPTION_NO_OPTION); |
||
| 170 | } |
||
| 171 | |||
| 172 | return $priceOptions; |
||
| 173 | } |
||
| 174 | |||
| 175 | /** |
||
| 176 | * @param string[] $overrideOptions |
||
| 177 | * @param PricingOptionGroup[] $priceOptions |
||
| 178 | * @return PricingOptionGroup[] |
||
| 179 | */ |
||
| 180 | protected static function makeOverrideOptions($overrideOptions, $priceOptions) |
||
| 181 | { |
||
| 182 | $opt = []; |
||
| 183 | |||
| 184 | foreach ($overrideOptions as $overrideOption) { |
||
| 185 | if (!self::hasPricingGroup($overrideOption, $priceOptions)) { |
||
| 186 | $opt[] = new PricingOptionGroup($overrideOption); |
||
| 187 | } |
||
| 188 | } |
||
| 189 | |||
| 190 | return $opt; |
||
| 191 | } |
||
| 192 | |||
| 193 | /** |
||
| 194 | * @param string|null $validatingCarrier |
||
| 195 | * @return PricePnr13\PricingOptionGroup[] |
||
| 196 | */ |
||
| 197 | protected static function makePricingOptionForValidatingCarrier($validatingCarrier) |
||
| 198 | { |
||
| 199 | $opt = []; |
||
| 200 | |||
| 201 | if ($validatingCarrier !== null) { |
||
| 202 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_VALIDATING_CARRIER); |
||
| 203 | |||
| 204 | $po->carrierInformation = new CarrierInformation($validatingCarrier); |
||
| 205 | |||
| 206 | $opt[] = $po; |
||
| 207 | } |
||
| 208 | |||
| 209 | return $opt; |
||
| 210 | } |
||
| 211 | |||
| 212 | /** |
||
| 213 | * @param string|null $currency |
||
| 214 | * @return PricePnr13\PricingOptionGroup[] |
||
| 215 | */ |
||
| 216 | protected static function makePricingOptionForCurrencyOverride($currency) |
||
| 217 | { |
||
| 218 | $opt = []; |
||
| 219 | |||
| 220 | if ($currency !== null) { |
||
| 221 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_FARE_CURRENCY_OVERRIDE); |
||
| 222 | |||
| 223 | $po->currency = new Currency($currency, FirstCurrencyDetails::QUAL_CURRENCY_OVERRIDE); |
||
| 224 | |||
| 225 | $opt[] = $po; |
||
| 226 | } |
||
| 227 | |||
| 228 | return $opt; |
||
| 229 | } |
||
| 230 | |||
| 231 | /** |
||
| 232 | * @param FareBasis[] $pricingsFareBasis |
||
| 233 | * @return PricePnr13\PricingOptionGroup[] |
||
| 234 | */ |
||
| 235 | protected static function makePricingOptionFareBasisOverride($pricingsFareBasis) |
||
| 236 | { |
||
| 237 | $opt = []; |
||
| 238 | |||
| 239 | if ($pricingsFareBasis !== null) { |
||
| 240 | foreach ($pricingsFareBasis as $pricingFareBasis) { |
||
| 241 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_FARE_BASIS_SIMPLE_OVERRIDE); |
||
| 242 | |||
| 243 | //Support for legacy fareBasisPrimaryCode to be removed when breaking BC: |
||
| 244 | $po->optionDetail = new OptionDetail( |
||
| 245 | $pricingFareBasis->fareBasisPrimaryCode . $pricingFareBasis->fareBasisCode |
||
|
|
|||
| 246 | ); |
||
| 247 | |||
| 248 | //Support for legacy segmentReference to be removed when breaking BC: |
||
| 249 | $po->paxSegTstReference = new PaxSegTstReference( |
||
| 250 | $pricingFareBasis->segmentReference, |
||
| 251 | $pricingFareBasis->references |
||
| 252 | ); |
||
| 253 | |||
| 254 | $opt[] = $po; |
||
| 255 | } |
||
| 256 | } |
||
| 257 | |||
| 258 | return $opt; |
||
| 259 | } |
||
| 260 | |||
| 261 | /** |
||
| 262 | * Load corporate negofare |
||
| 263 | * |
||
| 264 | * @param string|null $corporateNegoFare |
||
| 265 | * @return PricingOptionGroup[] |
||
| 266 | */ |
||
| 267 | View Code Duplication | protected static function loadCorpNegoFare($corporateNegoFare) |
|
| 268 | { |
||
| 269 | $opt = []; |
||
| 270 | |||
| 271 | if ($corporateNegoFare !== null) { |
||
| 272 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_CORPORATE_NEGOTIATED_FARES); |
||
| 273 | |||
| 274 | $po->optionDetail = new OptionDetail($corporateNegoFare); |
||
| 275 | |||
| 276 | $opt[] = $po; |
||
| 277 | } |
||
| 278 | |||
| 279 | return $opt; |
||
| 280 | } |
||
| 281 | |||
| 282 | /** |
||
| 283 | * Load corporate unifares |
||
| 284 | * |
||
| 285 | * @param string[] $corporateUniFares |
||
| 286 | * @param AwardPricing|null $awardPricing |
||
| 287 | * @return PricingOptionGroup[] |
||
| 288 | */ |
||
| 289 | protected static function loadCorpUniFares($corporateUniFares, $awardPricing) |
||
| 290 | { |
||
| 291 | $opt = []; |
||
| 292 | |||
| 293 | if (!empty($corporateUniFares)) { |
||
| 294 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_CORPORATE_UNIFARES); |
||
| 295 | $po->optionDetail = new OptionDetail($corporateUniFares); |
||
| 296 | $opt[] = $po; |
||
| 297 | |||
| 298 | if (!empty($awardPricing)) { |
||
| 299 | $opt[] = self::loadAwardPricing($awardPricing); |
||
| 300 | } |
||
| 301 | } |
||
| 302 | |||
| 303 | return $opt; |
||
| 304 | } |
||
| 305 | |||
| 306 | /** |
||
| 307 | * @param AwardPricing $awardPricing |
||
| 308 | * @return PricingOptionGroup |
||
| 309 | */ |
||
| 310 | protected static function loadAwardPricing($awardPricing) |
||
| 311 | { |
||
| 312 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_AWARD_PRICING); |
||
| 313 | |||
| 314 | $po->carrierInformation = new CarrierInformation($awardPricing->carrier); |
||
| 315 | |||
| 316 | $po->frequentFlyerInformation = new FrequentFlyerInformation(); |
||
| 317 | $po->frequentFlyerInformation->frequentTravellerDetails[] = new FrequentTravellerDetails( |
||
| 318 | $awardPricing->tierLevel |
||
| 319 | ); |
||
| 320 | |||
| 321 | return $po; |
||
| 322 | } |
||
| 323 | |||
| 324 | /** |
||
| 325 | * Load OB Fees |
||
| 326 | * |
||
| 327 | * @param ObFee[] $obFees |
||
| 328 | * @param PaxSegRef[] $obFeeRefs |
||
| 329 | * @return PricingOptionGroup[] |
||
| 330 | */ |
||
| 331 | View Code Duplication | protected static function loadObFees($obFees, $obFeeRefs) |
|
| 332 | { |
||
| 333 | $opt = []; |
||
| 334 | |||
| 335 | if (!empty($obFees)) { |
||
| 336 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_OB_FEES); |
||
| 337 | |||
| 338 | $po->penDisInformation = new PenDisInformation( |
||
| 339 | PenDisInformation::QUAL_OB_FEES, |
||
| 340 | $obFees |
||
| 341 | ); |
||
| 342 | |||
| 343 | if (!empty($obFeeRefs)) { |
||
| 344 | $po->paxSegTstReference = new PaxSegTstReference(null, $obFeeRefs); |
||
| 345 | } |
||
| 346 | |||
| 347 | $opt[] = $po; |
||
| 348 | } |
||
| 349 | |||
| 350 | return $opt; |
||
| 351 | } |
||
| 352 | |||
| 353 | /** |
||
| 354 | * @param string[] $paxDiscount |
||
| 355 | * @param PaxSegRef[] $paxDiscountCodeRefs |
||
| 356 | * @return PricingOptionGroup[] |
||
| 357 | */ |
||
| 358 | View Code Duplication | protected static function loadPaxDiscount($paxDiscount, $paxDiscountCodeRefs) |
|
| 359 | { |
||
| 360 | $opt = []; |
||
| 361 | |||
| 362 | if (!empty($paxDiscount)) { |
||
| 363 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_PASSENGER_DISCOUNT_PTC); |
||
| 364 | |||
| 365 | $po->penDisInformation = new PenDisInformation( |
||
| 366 | PenDisInformation::QUAL_DISCOUNT, |
||
| 367 | $paxDiscount |
||
| 368 | ); |
||
| 369 | |||
| 370 | if (!empty($paxDiscountCodeRefs)) { |
||
| 371 | $po->paxSegTstReference = new PaxSegTstReference(null, $paxDiscountCodeRefs); |
||
| 372 | } |
||
| 373 | |||
| 374 | $opt[] = $po; |
||
| 375 | } |
||
| 376 | |||
| 377 | return $opt; |
||
| 378 | } |
||
| 379 | |||
| 380 | /** |
||
| 381 | * @param string|null $posOverride |
||
| 382 | * @param string|null $potOverride |
||
| 383 | * @return PricingOptionGroup[] |
||
| 384 | */ |
||
| 385 | protected static function loadPointOverrides($posOverride, $potOverride) |
||
| 386 | { |
||
| 387 | $opt = []; |
||
| 388 | |||
| 389 | View Code Duplication | if (!empty($posOverride)) { |
|
| 390 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_POINT_OF_SALE_OVERRIDE); |
||
| 391 | |||
| 392 | $po->locationInformation = new LocationInformation( |
||
| 393 | LocationInformation::TYPE_POINT_OF_SALE, |
||
| 394 | $posOverride |
||
| 395 | ); |
||
| 396 | |||
| 397 | $opt[] = $po; |
||
| 398 | } |
||
| 399 | |||
| 400 | View Code Duplication | if (!empty($potOverride)) { |
|
| 401 | $po2 = new PricingOptionGroup(PricingOptionKey::OPTION_POINT_OF_TICKETING_OVERRIDE); |
||
| 402 | |||
| 403 | $po2->locationInformation = new LocationInformation( |
||
| 404 | LocationInformation::TYPE_POINT_OF_TICKETING, |
||
| 405 | $potOverride |
||
| 406 | ); |
||
| 407 | |||
| 408 | $opt[] = $po2; |
||
| 409 | } |
||
| 410 | |||
| 411 | return $opt; |
||
| 412 | } |
||
| 413 | |||
| 414 | /** |
||
| 415 | * @param string|null $pricingLogic |
||
| 416 | * @return PricingOptionGroup[] |
||
| 417 | */ |
||
| 418 | View Code Duplication | protected static function loadPricingLogic($pricingLogic) |
|
| 419 | { |
||
| 420 | $opt = []; |
||
| 421 | |||
| 422 | if (!empty($pricingLogic)) { |
||
| 423 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_PRICING_LOGIC); |
||
| 424 | $po->optionDetail = new OptionDetail($pricingLogic); |
||
| 425 | $opt[] = $po; |
||
| 426 | } |
||
| 427 | |||
| 428 | return $opt; |
||
| 429 | } |
||
| 430 | |||
| 431 | /** |
||
| 432 | * @param string|null $ticketType |
||
| 433 | * @return PricingOptionGroup[] |
||
| 434 | */ |
||
| 435 | View Code Duplication | protected static function loadTicketType($ticketType) |
|
| 436 | { |
||
| 437 | $opt = []; |
||
| 438 | |||
| 439 | if (!empty($ticketType)) { |
||
| 440 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_TICKET_TYPE); |
||
| 441 | |||
| 442 | $po->optionDetail = new OptionDetail($ticketType); |
||
| 443 | |||
| 444 | $opt[] = $po; |
||
| 445 | } |
||
| 446 | |||
| 447 | return $opt; |
||
| 448 | } |
||
| 449 | |||
| 450 | /** |
||
| 451 | * @param Tax[] $taxes |
||
| 452 | * @return PricingOptionGroup[] |
||
| 453 | */ |
||
| 454 | protected static function loadTaxes($taxes) |
||
| 455 | { |
||
| 456 | $opt = []; |
||
| 457 | |||
| 458 | if (!empty($taxes)) { |
||
| 459 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_ADD_TAX); |
||
| 460 | |||
| 461 | foreach ($taxes as $tax) { |
||
| 462 | $qualifier = (!empty($tax->amount)) ? TaxData::QUALIFIER_AMOUNT : TaxData::QUALIFIER_PERCENTAGE; |
||
| 463 | $rate = (!empty($tax->amount)) ? $tax->amount : $tax->percentage; |
||
| 464 | |||
| 465 | $po->taxInformation[] = new TaxInformation( |
||
| 466 | $tax->countryCode, |
||
| 467 | $tax->taxNature, |
||
| 468 | $qualifier, |
||
| 469 | $rate |
||
| 470 | ); |
||
| 471 | } |
||
| 472 | $opt[] = $po; |
||
| 473 | } |
||
| 474 | |||
| 475 | return $opt; |
||
| 476 | } |
||
| 477 | |||
| 478 | /** |
||
| 479 | * @param ExemptTax[] $exemptTaxes |
||
| 480 | * @return PricingOptionGroup[] |
||
| 481 | */ |
||
| 482 | protected static function loadExemptTaxes($exemptTaxes) |
||
| 483 | { |
||
| 484 | $opt = []; |
||
| 485 | |||
| 486 | if (!empty($exemptTaxes)) { |
||
| 487 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_EXEMPT_FROM_TAX); |
||
| 488 | |||
| 489 | foreach ($exemptTaxes as $tax) { |
||
| 490 | $po->taxInformation[] = new TaxInformation( |
||
| 491 | $tax->countryCode, |
||
| 492 | $tax->taxNature |
||
| 493 | ); |
||
| 494 | } |
||
| 495 | |||
| 496 | $opt[] = $po; |
||
| 497 | } |
||
| 498 | |||
| 499 | return $opt; |
||
| 500 | } |
||
| 501 | |||
| 502 | /** |
||
| 503 | * @param \DateTime|null $pastDate |
||
| 504 | * @return PricingOptionGroup[] |
||
| 505 | */ |
||
| 506 | protected static function loadPastDate($pastDate) |
||
| 507 | { |
||
| 508 | $opt = []; |
||
| 509 | |||
| 510 | if ($pastDate instanceof \DateTime) { |
||
| 511 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_PAST_DATE_PRICING); |
||
| 512 | |||
| 513 | $po->dateInformation = new DateInformation( |
||
| 514 | DateInformation::OPT_DATE_OVERRIDE, |
||
| 515 | $pastDate |
||
| 516 | ); |
||
| 517 | |||
| 518 | $opt[] = $po; |
||
| 519 | } |
||
| 520 | |||
| 521 | return $opt; |
||
| 522 | } |
||
| 523 | |||
| 524 | /** |
||
| 525 | * @param PaxSegRef[] $references |
||
| 526 | * @return PricingOptionGroup[] |
||
| 527 | */ |
||
| 528 | protected static function loadReferences($references) |
||
| 529 | { |
||
| 530 | $opt = []; |
||
| 531 | |||
| 532 | View Code Duplication | if (!empty($references)) { |
|
| 533 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_PAX_SEGMENT_TST_SELECTION); |
||
| 534 | |||
| 535 | $po->paxSegTstReference = new PaxSegTstReference(null, $references); |
||
| 536 | |||
| 537 | $opt[] = $po; |
||
| 538 | } |
||
| 539 | |||
| 540 | return $opt; |
||
| 541 | } |
||
| 542 | |||
| 543 | /** |
||
| 544 | * Avoid double pricing groups when combining an explicitly provided override option with a specific parameter |
||
| 545 | * that uses the same override option. |
||
| 546 | * |
||
| 547 | * Backwards compatibility with PricePnrWithBookingClass12 |
||
| 548 | * |
||
| 549 | * @param string $optionKey |
||
| 550 | * @param PricingOptionGroup[] $priceOptions |
||
| 551 | * @return bool |
||
| 552 | */ |
||
| 553 | protected static function hasPricingGroup($optionKey, $priceOptions) |
||
| 565 | |||
| 566 | /** |
||
| 567 | * Merges Pricing options |
||
| 568 | * |
||
| 569 | * @param PricingOptionGroup[] $existingOptions |
||
| 570 | * @param PricingOptionGroup[] $newOptions |
||
| 571 | * @return PricingOptionGroup[] merged array |
||
| 572 | */ |
||
| 573 | protected static function mergeOptions($existingOptions, $newOptions) |
||
| 584 | } |
||
| 585 |
This property has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.