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 |
||
59 | class PricePNRWithBookingClass13 extends BasePricingMessage |
||
60 | { |
||
61 | /** |
||
62 | * @var PricePnr13\PricingOptionGroup[] |
||
63 | */ |
||
64 | public $pricingOptionGroup = []; |
||
65 | |||
66 | /** |
||
67 | * PricePNRWithBookingClass13 constructor. |
||
68 | * |
||
69 | * @param FarePricePnrWithBookingClassOptions|LowerFareOpt|LowestFareOpt|InformativePriceOpt|null $options |
||
70 | * @throws MessageVersionUnsupportedException |
||
71 | */ |
||
72 | 72 | public function __construct($options) |
|
78 | |||
79 | /** |
||
80 | * Load an array of PricingOptionGroup objects from the Pricing request options. |
||
81 | * |
||
82 | * Extracted because this method is also used in the InformativePricingWithoutPnr messages. |
||
83 | * |
||
84 | * @param FarePricePnrWithBookingClassOptions|LowerFareOpt|LowestFareOpt|InformativePriceOpt $options |
||
85 | * @return PricingOptionGroup[] |
||
86 | */ |
||
87 | 99 | public static function loadPricingOptionsFromRequestOptions($options) |
|
88 | { |
||
89 | 99 | $priceOptions = []; |
|
90 | |||
91 | 99 | $priceOptions = self::mergeOptions( |
|
92 | 99 | $priceOptions, |
|
93 | 99 | self::makePricingOptionForValidatingCarrier($options->validatingCarrier) |
|
94 | ); |
||
95 | |||
96 | 99 | $priceOptions = self::mergeOptions( |
|
97 | 99 | $priceOptions, |
|
98 | 99 | self::makePricingOptionForCurrencyOverride($options->currencyOverride) |
|
99 | ); |
||
100 | |||
101 | 99 | $priceOptions = self::mergeOptions( |
|
102 | 99 | $priceOptions, |
|
103 | 99 | self::makePricingOptionFareBasisOverride($options->pricingsFareBasis) |
|
104 | ); |
||
105 | |||
106 | 99 | $priceOptions = self::mergeOptions( |
|
107 | 99 | $priceOptions, |
|
108 | 99 | self::makePricingOptionFareFamilyOverride($options->fareFamily) |
|
109 | ); |
||
110 | |||
111 | 99 | $priceOptions = self::mergeOptions( |
|
112 | 99 | $priceOptions, |
|
113 | 99 | self::loadCorpNegoFare($options->corporateNegoFare) |
|
114 | ); |
||
115 | |||
116 | 99 | $priceOptions = self::mergeOptions( |
|
117 | 99 | $priceOptions, |
|
118 | 99 | self::loadCorpUniFares($options->corporateUniFares, $options->awardPricing) |
|
119 | ); |
||
120 | |||
121 | 99 | $priceOptions = self::mergeOptions( |
|
122 | 99 | $priceOptions, |
|
123 | 99 | self::loadObFees($options->obFees, $options->obFeeRefs) |
|
124 | ); |
||
125 | |||
126 | 99 | $priceOptions = self::mergeOptions( |
|
127 | 99 | $priceOptions, |
|
128 | 99 | self::loadPaxDiscount($options->paxDiscountCodes, $options->paxDiscountCodeRefs) |
|
129 | ); |
||
130 | |||
131 | 99 | $priceOptions = self::mergeOptions( |
|
132 | 99 | $priceOptions, |
|
133 | 99 | self::loadPointOverrides( |
|
134 | 99 | $options->pointOfSaleOverride, |
|
135 | 99 | $options->pointOfTicketingOverride |
|
136 | ) |
||
137 | ); |
||
138 | |||
139 | 99 | $priceOptions = self::mergeOptions( |
|
140 | 99 | $priceOptions, |
|
141 | 99 | self::loadPricingLogic($options->pricingLogic) |
|
142 | ); |
||
143 | |||
144 | 99 | $priceOptions = self::mergeOptions( |
|
145 | 99 | $priceOptions, |
|
146 | 99 | self::loadTicketType($options->ticketType) |
|
147 | ); |
||
148 | |||
149 | 99 | $priceOptions = self::mergeOptions( |
|
150 | 99 | $priceOptions, |
|
151 | 99 | self::loadTaxes($options->taxes) |
|
152 | ); |
||
153 | |||
154 | 99 | $priceOptions = self::mergeOptions( |
|
155 | 99 | $priceOptions, |
|
156 | 99 | self::loadExemptTaxes($options->exemptTaxes) |
|
157 | ); |
||
158 | |||
159 | 99 | $priceOptions = self::mergeOptions( |
|
160 | 99 | $priceOptions, |
|
161 | 99 | self::loadPastDate($options->pastDatePricing) |
|
162 | ); |
||
163 | |||
164 | |||
165 | 99 | $priceOptions = self::mergeOptions( |
|
166 | 99 | $priceOptions, |
|
167 | 99 | self::loadFormOfPayment($options->formOfPayment) |
|
168 | ); |
||
169 | |||
170 | 99 | $priceOptions = self::mergeOptions( |
|
171 | 99 | $priceOptions, |
|
172 | 99 | self::loadReferences($options->references) |
|
173 | ); |
||
174 | |||
175 | 99 | $priceOptions = self::mergeOptions( |
|
176 | 99 | $priceOptions, |
|
177 | 99 | self::makeOverrideOptions($options->overrideOptions, $priceOptions) |
|
178 | ); |
||
179 | |||
180 | 99 | $priceOptions = self::mergeOptions( |
|
181 | 99 | $priceOptions, |
|
182 | 99 | self::makeOverrideOptionsWithCriteria($options->overrideOptionsWithCriteria, $priceOptions) |
|
183 | ); |
||
184 | |||
185 | 99 | $priceOptions = self::mergeOptions( |
|
186 | 99 | $priceOptions, |
|
187 | 99 | self::loadZapOffs($options->zapOff) |
|
188 | ); |
||
189 | |||
190 | // All options processed, no options found: |
||
191 | 99 | if (empty($priceOptions)) { |
|
192 | 18 | $priceOptions[] = new PricingOptionGroup(PricingOptionKey::OPTION_NO_OPTION); |
|
193 | } |
||
194 | |||
195 | 99 | return $priceOptions; |
|
196 | } |
||
197 | |||
198 | /** |
||
199 | * @param string[] $overrideOptions |
||
200 | * @param PricingOptionGroup[] $priceOptions |
||
201 | * @return PricingOptionGroup[] |
||
202 | */ |
||
203 | 99 | View Code Duplication | protected static function makeOverrideOptions($overrideOptions, $priceOptions) |
|
|||
204 | { |
||
205 | 99 | $opt = []; |
|
206 | |||
207 | 99 | foreach ($overrideOptions as $overrideOption) { |
|
208 | 24 | if (!self::hasPricingGroup($overrideOption, $priceOptions)) { |
|
209 | 24 | $opt[] = new PricingOptionGroup($overrideOption); |
|
210 | } |
||
211 | } |
||
212 | |||
213 | 99 | return $opt; |
|
214 | } |
||
215 | |||
216 | /** |
||
217 | * @param string[] $overrideOptionsWithCriteria |
||
218 | * @param PricingOptionGroup[] $priceOptions |
||
219 | * @return PricingOptionGroup[] |
||
220 | */ |
||
221 | 99 | protected static function makeOverrideOptionsWithCriteria($overrideOptionsWithCriteria, $priceOptions) |
|
222 | { |
||
223 | 99 | $opt = []; |
|
224 | |||
225 | 99 | foreach ($overrideOptionsWithCriteria as $overrideOptionWithCriteria) { |
|
226 | 3 | if (!self::hasPricingGroup($overrideOptionWithCriteria["key"], $priceOptions)) { |
|
227 | 3 | $opt[] = new PricingOptionGroup($overrideOptionWithCriteria["key"], $overrideOptionWithCriteria["optionDetail"]); |
|
228 | } |
||
229 | } |
||
230 | |||
231 | 99 | return $opt; |
|
232 | } |
||
233 | |||
234 | /** |
||
235 | * @param string|null $validatingCarrier |
||
236 | * @return PricePnr13\PricingOptionGroup[] |
||
237 | */ |
||
238 | 99 | View Code Duplication | protected static function makePricingOptionForValidatingCarrier($validatingCarrier) |
239 | { |
||
240 | 99 | $opt = []; |
|
241 | |||
242 | 99 | if ($validatingCarrier !== null) { |
|
243 | 24 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_VALIDATING_CARRIER); |
|
244 | |||
245 | 24 | $po->carrierInformation = new CarrierInformation($validatingCarrier); |
|
246 | |||
247 | 24 | $opt[] = $po; |
|
248 | } |
||
249 | |||
250 | 99 | return $opt; |
|
251 | } |
||
252 | |||
253 | /** |
||
254 | * @param string|null $currency |
||
255 | * @return PricePnr13\PricingOptionGroup[] |
||
256 | */ |
||
257 | 99 | View Code Duplication | protected static function makePricingOptionForCurrencyOverride($currency) |
258 | { |
||
259 | 99 | $opt = []; |
|
260 | |||
261 | 99 | if ($currency !== null) { |
|
262 | 24 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_FARE_CURRENCY_OVERRIDE); |
|
263 | |||
264 | 24 | $po->currency = new Currency($currency); |
|
265 | |||
266 | 24 | $opt[] = $po; |
|
267 | } |
||
268 | |||
269 | 99 | return $opt; |
|
270 | } |
||
271 | |||
272 | |||
273 | /** |
||
274 | * @param FareBasis[] $pricingsFareBasis |
||
275 | * @return PricePnr13\PricingOptionGroup[] |
||
276 | */ |
||
277 | 99 | View Code Duplication | protected static function makePricingOptionFareBasisOverride($pricingsFareBasis) |
302 | |||
303 | /** |
||
304 | * Load fare-family pricing option and return it. |
||
305 | * |
||
306 | * @param string $fareFamily input fare-family, e.g. "CLASSIC" |
||
307 | * @return PricePnr13\PricingOptionGroup[] |
||
308 | */ |
||
309 | 99 | protected static function makePricingOptionFareFamilyOverride($fareFamily) |
|
310 | { |
||
311 | 99 | $opt = []; |
|
312 | |||
313 | 99 | if ($fareFamily !== null) { |
|
314 | 3 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_FARE_FAMILY); |
|
315 | 3 | $po->optionDetail = new OptionDetail([['FF' => $fareFamily]]); |
|
316 | |||
317 | 3 | $opt[] = $po; |
|
318 | } |
||
319 | |||
320 | 99 | return $opt; |
|
321 | } |
||
322 | |||
323 | /** |
||
324 | * Load corporate negofare |
||
325 | * |
||
326 | * @param string|null $corporateNegoFare |
||
327 | * @return PricingOptionGroup[] |
||
328 | */ |
||
329 | 99 | View Code Duplication | protected static function loadCorpNegoFare($corporateNegoFare) |
330 | { |
||
331 | 99 | $opt = []; |
|
332 | |||
333 | 99 | if ($corporateNegoFare !== null) { |
|
334 | 3 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_CORPORATE_NEGOTIATED_FARES); |
|
335 | |||
336 | 3 | $po->optionDetail = new OptionDetail($corporateNegoFare); |
|
337 | |||
338 | 3 | $opt[] = $po; |
|
339 | } |
||
340 | |||
341 | 99 | return $opt; |
|
342 | } |
||
343 | |||
344 | /** |
||
345 | * Load corporate unifares |
||
346 | * |
||
347 | * @param string[] $corporateUniFares |
||
348 | * @param AwardPricing|null $awardPricing |
||
349 | * @return PricingOptionGroup[] |
||
350 | */ |
||
351 | 99 | protected static function loadCorpUniFares($corporateUniFares, $awardPricing) |
|
352 | { |
||
353 | 99 | $opt = []; |
|
354 | |||
355 | 99 | if (!empty($corporateUniFares)) { |
|
356 | 6 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_CORPORATE_UNIFARES); |
|
357 | 6 | $po->optionDetail = new OptionDetail($corporateUniFares); |
|
358 | 6 | $opt[] = $po; |
|
359 | |||
360 | 6 | if (!empty($awardPricing)) { |
|
361 | 3 | $opt[] = self::loadAwardPricing($awardPricing); |
|
362 | } |
||
363 | } |
||
364 | |||
365 | 99 | return $opt; |
|
366 | } |
||
367 | |||
368 | /** |
||
369 | * @param AwardPricing $awardPricing |
||
370 | * @return PricingOptionGroup |
||
371 | */ |
||
372 | 3 | View Code Duplication | protected static function loadAwardPricing($awardPricing) |
373 | { |
||
374 | 3 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_AWARD_PRICING); |
|
375 | |||
376 | 3 | $po->carrierInformation = new CarrierInformation($awardPricing->carrier); |
|
377 | |||
378 | 3 | $po->frequentFlyerInformation = new FrequentFlyerInformation(); |
|
379 | 3 | $po->frequentFlyerInformation->frequentTravellerDetails[] = new FrequentTravellerDetails( |
|
380 | 3 | $awardPricing->tierLevel |
|
381 | ); |
||
382 | |||
383 | 3 | return $po; |
|
384 | } |
||
385 | |||
386 | /** |
||
387 | * Load OB Fees |
||
388 | * |
||
389 | * @param ObFee[] $obFees |
||
390 | * @param PaxSegRef[] $obFeeRefs |
||
391 | * @return PricingOptionGroup[] |
||
392 | */ |
||
393 | 99 | View Code Duplication | protected static function loadObFees($obFees, $obFeeRefs) |
394 | { |
||
395 | 99 | $opt = []; |
|
396 | |||
397 | 99 | if (!empty($obFees)) { |
|
398 | 3 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_OB_FEES); |
|
399 | |||
400 | 3 | $po->penDisInformation = new PenDisInformation( |
|
401 | 3 | PenDisInformation::QUAL_OB_FEES, |
|
402 | 2 | $obFees |
|
403 | ); |
||
404 | |||
405 | 3 | if (!empty($obFeeRefs)) { |
|
406 | 3 | $po->paxSegTstReference = new PaxSegTstReference($obFeeRefs); |
|
407 | } |
||
408 | |||
409 | 3 | $opt[] = $po; |
|
410 | } |
||
411 | |||
412 | 99 | return $opt; |
|
413 | } |
||
414 | |||
415 | /** |
||
416 | * @param string[] $paxDiscount |
||
417 | * @param PaxSegRef[] $paxDiscountCodeRefs |
||
418 | * @return PricingOptionGroup[] |
||
419 | */ |
||
420 | 99 | View Code Duplication | protected static function loadPaxDiscount($paxDiscount, $paxDiscountCodeRefs) |
421 | { |
||
422 | 99 | $opt = []; |
|
423 | |||
424 | 99 | if (!empty($paxDiscount)) { |
|
425 | 12 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_PASSENGER_DISCOUNT_PTC); |
|
426 | |||
427 | 12 | $po->penDisInformation = new PenDisInformation( |
|
428 | 12 | PenDisInformation::QUAL_DISCOUNT, |
|
429 | 8 | $paxDiscount |
|
430 | ); |
||
431 | |||
432 | 12 | if (!empty($paxDiscountCodeRefs)) { |
|
433 | 12 | $po->paxSegTstReference = new PaxSegTstReference($paxDiscountCodeRefs); |
|
434 | } |
||
435 | |||
436 | 12 | $opt[] = $po; |
|
437 | } |
||
438 | |||
439 | 99 | return $opt; |
|
440 | } |
||
441 | |||
442 | /** |
||
443 | * @param string|null $posOverride |
||
444 | * @param string|null $potOverride |
||
445 | * @return PricingOptionGroup[] |
||
446 | */ |
||
447 | 99 | View Code Duplication | protected static function loadPointOverrides($posOverride, $potOverride) |
448 | { |
||
449 | 99 | $opt = []; |
|
450 | |||
451 | 99 | if (!empty($posOverride)) { |
|
452 | 3 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_POINT_OF_SALE_OVERRIDE); |
|
453 | |||
454 | 3 | $po->locationInformation = new LocationInformation( |
|
455 | 3 | LocationInformation::TYPE_POINT_OF_SALE, |
|
456 | 2 | $posOverride |
|
457 | ); |
||
458 | |||
459 | 3 | $opt[] = $po; |
|
460 | } |
||
461 | |||
462 | 99 | if (!empty($potOverride)) { |
|
463 | 3 | $po2 = new PricingOptionGroup(PricingOptionKey::OPTION_POINT_OF_TICKETING_OVERRIDE); |
|
464 | |||
465 | 3 | $po2->locationInformation = new LocationInformation( |
|
466 | 3 | LocationInformation::TYPE_POINT_OF_TICKETING, |
|
467 | 2 | $potOverride |
|
468 | ); |
||
469 | |||
470 | 3 | $opt[] = $po2; |
|
471 | } |
||
472 | |||
473 | 99 | return $opt; |
|
474 | } |
||
475 | |||
476 | /** |
||
477 | * @param string|null $pricingLogic |
||
478 | * @return PricingOptionGroup[] |
||
479 | */ |
||
480 | 99 | View Code Duplication | protected static function loadPricingLogic($pricingLogic) |
481 | { |
||
482 | 99 | $opt = []; |
|
483 | |||
484 | 99 | if (!empty($pricingLogic)) { |
|
485 | 3 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_PRICING_LOGIC); |
|
486 | 3 | $po->optionDetail = new OptionDetail($pricingLogic); |
|
487 | 3 | $opt[] = $po; |
|
488 | } |
||
489 | |||
490 | 99 | return $opt; |
|
491 | } |
||
492 | |||
493 | /** |
||
494 | * @param string|null $ticketType |
||
495 | * @return PricingOptionGroup[] |
||
496 | */ |
||
497 | 99 | View Code Duplication | protected static function loadTicketType($ticketType) |
498 | { |
||
499 | 99 | $opt = []; |
|
500 | |||
501 | 99 | if (!empty($ticketType)) { |
|
502 | 3 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_TICKET_TYPE); |
|
503 | |||
504 | 3 | $po->optionDetail = new OptionDetail($ticketType); |
|
505 | |||
506 | 3 | $opt[] = $po; |
|
507 | } |
||
508 | |||
509 | 99 | return $opt; |
|
510 | } |
||
511 | |||
512 | /** |
||
513 | * @param Tax[] $taxes |
||
514 | * @return PricingOptionGroup[] |
||
515 | */ |
||
516 | 99 | View Code Duplication | protected static function loadTaxes($taxes) |
539 | |||
540 | /** |
||
541 | * @param ExemptTax[] $exemptTaxes |
||
542 | * @return PricingOptionGroup[] |
||
543 | */ |
||
544 | 99 | View Code Duplication | protected static function loadExemptTaxes($exemptTaxes) |
563 | |||
564 | /** |
||
565 | * @param \DateTime|null $pastDate |
||
566 | * @return PricingOptionGroup[] |
||
567 | */ |
||
568 | 99 | View Code Duplication | protected static function loadPastDate($pastDate) |
569 | { |
||
570 | 99 | $opt = []; |
|
571 | |||
572 | 99 | if ($pastDate instanceof \DateTime) { |
|
573 | 3 | $po = new PricingOptionGroup(PricingOptionKey::OPTION_PAST_DATE_PRICING); |
|
574 | |||
575 | 3 | $po->dateInformation = new DateInformation( |
|
576 | 3 | DateInformation::OPT_DATE_OVERRIDE, |
|
577 | 2 | $pastDate |
|
585 | |||
586 | |||
587 | /** |
||
588 | * @param FormOfPayment[] $formOfPayment |
||
589 | * @return PricingOptionGroup[] |
||
590 | */ |
||
591 | 99 | View Code Duplication | protected static function loadFormOfPayment($formOfPayment) |
605 | |||
606 | /** |
||
607 | * @param PaxSegRef[] $references |
||
608 | * @return PricingOptionGroup[] |
||
609 | */ |
||
610 | 99 | View Code Duplication | protected static function loadReferences($references) |
624 | |||
625 | /** |
||
626 | * Load ZAP-Off |
||
627 | * |
||
628 | * @param ZapOff[] $zapOffs |
||
629 | * @return PricingOptionGroup[] |
||
630 | */ |
||
631 | 99 | protected static function loadZapOffs($zapOffs) |
|
653 | } |
||
654 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.