Complex classes like ManagingProductsContext 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 ManagingProductsContext, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
39 | final class ManagingProductsContext implements Context |
||
40 | { |
||
41 | /** |
||
42 | * @var SharedStorageInterface |
||
43 | */ |
||
44 | private $sharedStorage; |
||
45 | |||
46 | /**x |
||
47 | * @var CreateSimpleProductPageInterface |
||
48 | */ |
||
49 | private $createSimpleProductPage; |
||
50 | |||
51 | /** |
||
52 | * @var CreateConfigurableProductPageInterface |
||
53 | */ |
||
54 | private $createConfigurableProductPage; |
||
55 | |||
56 | /** |
||
57 | * @var IndexPageInterface |
||
58 | */ |
||
59 | private $indexPage; |
||
60 | |||
61 | /** |
||
62 | * @var UpdateSimpleProductPageInterface |
||
63 | */ |
||
64 | private $updateSimpleProductPage; |
||
65 | |||
66 | /** |
||
67 | * @var UpdateConfigurableProductPageInterface |
||
68 | */ |
||
69 | private $updateConfigurableProductPage; |
||
70 | |||
71 | /** |
||
72 | * @var ProductReviewIndexPageInterface |
||
73 | */ |
||
74 | private $productReviewIndexPage; |
||
75 | |||
76 | /** |
||
77 | * @var CurrentProductPageResolverInterface |
||
78 | */ |
||
79 | private $currentPageResolver; |
||
80 | |||
81 | /** |
||
82 | * @var NotificationCheckerInterface |
||
83 | */ |
||
84 | private $notificationChecker; |
||
85 | |||
86 | /** |
||
87 | * @param SharedStorageInterface $sharedStorage |
||
88 | * @param CreateSimpleProductPageInterface $createSimpleProductPage |
||
89 | * @param CreateConfigurableProductPageInterface $createConfigurableProductPage |
||
90 | * @param IndexPageInterface $indexPage |
||
91 | * @param UpdateSimpleProductPageInterface $updateSimpleProductPage |
||
92 | * @param UpdateConfigurableProductPageInterface $updateConfigurableProductPage |
||
93 | * @param ProductReviewIndexPageInterface $productReviewIndexPage |
||
94 | * @param CurrentProductPageResolverInterface $currentPageResolver |
||
95 | * @param NotificationCheckerInterface $notificationChecker |
||
96 | */ |
||
97 | public function __construct( |
||
118 | |||
119 | /** |
||
120 | * @Given I want to create a new simple product |
||
121 | */ |
||
122 | public function iWantToCreateANewSimpleProduct() |
||
126 | |||
127 | /** |
||
128 | * @Given I want to create a new configurable product |
||
129 | */ |
||
130 | public function iWantToCreateANewConfigurableProduct() |
||
134 | |||
135 | /** |
||
136 | * @When I specify its code as :code |
||
137 | * @When I do not specify its code |
||
138 | */ |
||
139 | public function iSpecifyItsCodeAs($code = null) |
||
148 | |||
149 | /** |
||
150 | * @When I name it :name in :language |
||
151 | */ |
||
152 | public function iNameItIn($name, $language) |
||
161 | |||
162 | /** |
||
163 | * @When I rename it to :name in :language |
||
164 | */ |
||
165 | public function iRenameItToIn($name, $language) |
||
174 | |||
175 | /** |
||
176 | * @When I add it |
||
177 | * @When I try to add it |
||
178 | */ |
||
179 | public function iAddIt() |
||
191 | |||
192 | /** |
||
193 | * @When I disable its inventory tracking |
||
194 | */ |
||
195 | public function iDisableItsTracking() |
||
199 | |||
200 | /** |
||
201 | * @When I enable its inventory tracking |
||
202 | */ |
||
203 | public function iEnableItsTracking() |
||
207 | |||
208 | /** |
||
209 | * @When /^I set its(?:| default) price to ("(?:€|£|\$)[^"]+")$/ |
||
210 | */ |
||
211 | public function iSetItsPriceTo($price) |
||
215 | |||
216 | /** |
||
217 | * @When I choose :calculatorName calculator |
||
218 | */ |
||
219 | public function iChooseCalculator($calculatorName) |
||
223 | |||
224 | /** |
||
225 | * @When /^I set its price to "(?:€|£|\$)([^"]+)" for ("[^"]+" currency) and ("[^"]+" channel)$/ |
||
226 | */ |
||
227 | public function iSetItsPriceToForCurrencyAndChannel($price, CurrencyInterface $currency, ChannelInterface $channel) |
||
231 | |||
232 | /** |
||
233 | * @When I set its slug to :slug |
||
234 | * @When I remove its slug |
||
235 | */ |
||
236 | public function iSetItsSlugTo($slug = null) |
||
240 | |||
241 | /** |
||
242 | * @When I enable slug modification |
||
243 | */ |
||
244 | public function iEnableSlugModification() |
||
248 | |||
249 | /** |
||
250 | * @Then the product :productName should appear in the shop |
||
251 | * @Then the product :productName should be in the shop |
||
252 | * @Then this product should still be named :productName |
||
253 | */ |
||
254 | public function theProductShouldAppearInTheShop($productName) |
||
263 | |||
264 | /** |
||
265 | * @Given I am browsing products |
||
266 | * @When I want to browse products |
||
267 | */ |
||
268 | public function iWantToBrowseProducts() |
||
272 | |||
273 | /** |
||
274 | * @When I filter them by :taxonName taxon |
||
275 | */ |
||
276 | public function iFilterThemByTaxon($taxonName) |
||
280 | |||
281 | /** |
||
282 | * @Then I should( still) see a product with :field :value |
||
283 | */ |
||
284 | public function iShouldSeeProductWith($field, $value) |
||
291 | |||
292 | /** |
||
293 | * @Then I should not see any product with :field :value |
||
294 | */ |
||
295 | public function iShouldNotSeeAnyProductWith($field, $value) |
||
302 | |||
303 | /** |
||
304 | * @Then the first product on the list should have :field :value |
||
305 | */ |
||
306 | public function theFirstProductOnTheListShouldHave($field, $value) |
||
316 | |||
317 | /** |
||
318 | * @When I switch the way products are sorted by :field |
||
319 | * @When I start sorting products by :field |
||
320 | * @Given the products are already sorted by :field |
||
321 | */ |
||
322 | public function iSortProductsBy($field) |
||
326 | |||
327 | /** |
||
328 | * @Then I should see :numberOfProducts products in the list |
||
329 | */ |
||
330 | public function iShouldSeeProductsInTheList($numberOfProducts) |
||
340 | |||
341 | /** |
||
342 | * @When I delete the :product product |
||
343 | * @When I try to delete the :product product |
||
344 | */ |
||
345 | public function iDeleteProduct(ProductInterface $product) |
||
352 | |||
353 | /** |
||
354 | * @Then /^(this product) should not exist in the product catalog$/ |
||
355 | */ |
||
356 | public function productShouldNotExist(ProductInterface $product) |
||
365 | |||
366 | /** |
||
367 | * @Then I should be notified that this product is in use and cannot be deleted |
||
368 | */ |
||
369 | public function iShouldBeNotifiedOfFailure() |
||
376 | |||
377 | /** |
||
378 | * @Then /^(this product) should still exist in the product catalog$/ |
||
379 | */ |
||
380 | public function productShouldExistInTheProductCatalog(ProductInterface $product) |
||
384 | |||
385 | /** |
||
386 | * @When I want to modify the :product product |
||
387 | * @When /^I want to modify (this product)$/ |
||
388 | */ |
||
389 | public function iWantToModifyAProduct(ProductInterface $product) |
||
400 | |||
401 | /** |
||
402 | * @Then the code field should be disabled |
||
403 | */ |
||
404 | public function theCodeFieldShouldBeDisabled() |
||
417 | |||
418 | /** |
||
419 | * @Then the slug field should not be editable |
||
420 | */ |
||
421 | public function theSlugFieldShouldNotBeEditable() |
||
428 | |||
429 | /** |
||
430 | * @Then /^this product price should be "(?:€|£|\$)([^"]+)"$/ |
||
431 | */ |
||
432 | public function thisProductPriceShouldBeEqualTo($price) |
||
436 | |||
437 | /** |
||
438 | * @Then this product name should be :name |
||
439 | */ |
||
440 | public function thisProductElementShouldBe($name) |
||
444 | |||
445 | /** |
||
446 | * @Then /^I should be notified that (code|name|slug) is required$/ |
||
447 | */ |
||
448 | public function iShouldBeNotifiedThatIsRequired($element) |
||
452 | |||
453 | /** |
||
454 | * @Then I should be notified that price is required |
||
455 | */ |
||
456 | public function iShouldBeNotifiedThatPriceIsRequired() |
||
460 | |||
461 | /** |
||
462 | * @When I save my changes |
||
463 | * @When I try to save my changes |
||
464 | */ |
||
465 | public function iSaveMyChanges() |
||
477 | |||
478 | /** |
||
479 | * @When /^I change its price to "(?:€|£|\$)([^"]+)"$/ |
||
480 | */ |
||
481 | public function iChangeItsPriceTo($price) |
||
485 | |||
486 | /** |
||
487 | * @Given I add the :optionName option to it |
||
488 | */ |
||
489 | public function iAddTheOptionToIt($optionName) |
||
493 | |||
494 | /** |
||
495 | * @When I set its :attribute attribute to :value |
||
496 | */ |
||
497 | public function iSetItsAttributeTo($attribute, $value) |
||
501 | |||
502 | /** |
||
503 | * @When I remove its :attribute attribute |
||
504 | */ |
||
505 | public function iRemoveItsAttribute($attribute) |
||
509 | |||
510 | /** |
||
511 | * @Then /^attribute "([^"]+)" of (product "[^"]+") should be "([^"]+)"$/ |
||
512 | */ |
||
513 | public function itsAttributeShouldBe($attribute, ProductInterface $product, $value) |
||
523 | |||
524 | /** |
||
525 | * @Then /^(product "[^"]+") should not have a "([^"]+)" attribute$/ |
||
526 | */ |
||
527 | public function productShouldNotHaveAttribute(ProductInterface $product, $attribute) |
||
536 | |||
537 | /** |
||
538 | * @Given product with :element :value should not be added |
||
539 | */ |
||
540 | public function productWithNameShouldNotBeAdded($element, $value) |
||
549 | |||
550 | /** |
||
551 | * @When I remove its name from :language translation |
||
552 | */ |
||
553 | public function iRemoveItsNameFromTranslation($language) |
||
562 | |||
563 | /** |
||
564 | * @Then /^this product should have (?:a|an) "([^"]+)" option$/ |
||
565 | */ |
||
566 | public function thisProductShouldHaveOption($productOption) |
||
570 | |||
571 | /** |
||
572 | * @Then the option field should be disabled |
||
573 | */ |
||
574 | public function theOptionFieldShouldBeDisabled() |
||
581 | |||
582 | /** |
||
583 | * @When /^I choose main (taxon "([^"]+)")$/ |
||
584 | */ |
||
585 | public function iChooseMainTaxon(TaxonInterface $taxon) |
||
594 | |||
595 | /** |
||
596 | * @Then /^the slug of the ("[^"]+" product) should(?:| still) be "([^"]+)"$/ |
||
597 | */ |
||
598 | public function productSlugShouldBe(ProductInterface $product, $slug) |
||
607 | |||
608 | /** |
||
609 | * @Then /^(this product) main taxon should be "([^"]+)"$/ |
||
610 | */ |
||
611 | public function thisProductMainTaxonShouldBe(ProductInterface $product, $taxonName) |
||
626 | |||
627 | /** |
||
628 | * @Then /^inventory of (this product) should not be tracked$/ |
||
629 | */ |
||
630 | public function thisProductShouldNotBeTracked(ProductInterface $product) |
||
639 | |||
640 | /** |
||
641 | * @Then /^inventory of (this product) should be tracked$/ |
||
642 | */ |
||
643 | public function thisProductShouldBeTracked(ProductInterface $product) |
||
652 | |||
653 | /** |
||
654 | * @When I attach the :path image with a code :code |
||
655 | */ |
||
656 | public function iAttachImageWithACode($path, $code) |
||
668 | |||
669 | /** |
||
670 | * @When I attach the :path image without a code |
||
671 | */ |
||
672 | public function iAttachImageWithoutACode($path) |
||
682 | |||
683 | /** |
||
684 | * @When I associate as :productAssociationType the :productName product |
||
685 | * @When I associate as :productAssociationType the :firstProductName and :secondProductName products |
||
686 | */ |
||
687 | public function iAssociateProductsAsProductAssociation( |
||
699 | |||
700 | /** |
||
701 | * @When I remove an associated product :productName from :productAssociationType |
||
702 | */ |
||
703 | public function iRemoveAnAssociatedProductFromProductAssociation( |
||
715 | |||
716 | /** |
||
717 | * @Then /^(this product) should have(?:| also) an image with a code "([^"]*)"$/ |
||
718 | * @Then /^the (product "[^"]+") should have(?:| also) an image with a code "([^"]*)"$/ |
||
719 | */ |
||
720 | public function thisProductShouldHaveAnImageWithCode(ProductInterface $product, $code) |
||
735 | |||
736 | /** |
||
737 | * @Then /^(this product) should not have(?:| also) an image with a code "([^"]*)"$/ |
||
738 | */ |
||
739 | public function thisProductShouldNotHaveAnImageWithCode(ProductInterface $product, $code) |
||
752 | |||
753 | /** |
||
754 | * @When I change the image with the :code code to :path |
||
755 | */ |
||
756 | public function iChangeItsImageToPathForTheCode($path, $code) |
||
766 | |||
767 | /** |
||
768 | * @When /^I remove(?:| also) an image with a code "([^"]*)"$/ |
||
769 | */ |
||
770 | public function iRemoveAnImageWithACode($code) |
||
780 | |||
781 | /** |
||
782 | * @When I remove the first image |
||
783 | */ |
||
784 | public function iRemoveTheFirstImage() |
||
794 | |||
795 | /** |
||
796 | * @Then /^(this product) should not have any images$/ |
||
797 | */ |
||
798 | public function thisProductShouldNotHaveImages(ProductInterface $product) |
||
814 | |||
815 | /** |
||
816 | * @Then the image code field should be disabled |
||
817 | */ |
||
818 | public function theImageCodeFieldShouldBeDisabled() |
||
831 | |||
832 | /** |
||
833 | * @Then I should be notified that the image with this code already exists |
||
834 | */ |
||
835 | public function iShouldBeNotifiedThatTheImageWithThisCodeAlreadyExists() |
||
839 | |||
840 | /** |
||
841 | * @Then I should be notified that an image code is required |
||
842 | */ |
||
843 | public function iShouldBeNotifiedThatAnImageCodeIsRequired() |
||
856 | |||
857 | /** |
||
858 | * @Then there should still be only one image in the :product product |
||
859 | */ |
||
860 | public function thereShouldStillBeOnlyOneImageInThisTaxon(ProductInterface $product) |
||
876 | |||
877 | /** |
||
878 | * @Then /^there should be no reviews of (this product)$/ |
||
879 | */ |
||
880 | public function thereAreNoProductReviews(ProductInterface $product) |
||
889 | |||
890 | /** |
||
891 | * @Then /^the product for ("[^"]+" currency) and ("[^"]+" channel) should have "(?:€|£|\$)([^"]+)"$/ |
||
892 | */ |
||
893 | public function theProductForCurrencyAndChannelShouldHave(CurrencyInterface $currency, ChannelInterface $channel, $price) |
||
900 | |||
901 | /** |
||
902 | * @Then this product should( also) have an association :productAssociationType with product :productName |
||
903 | * @Then this product should( also) have an association :productAssociationType with products :firstProductName and :secondProductName |
||
904 | */ |
||
905 | public function theProductShouldHaveAnAssociationWithProducts( |
||
920 | |||
921 | /** |
||
922 | * @Then this product should not have an association :productAssociationType with product :productName |
||
923 | */ |
||
924 | public function theProductShouldNotHaveAnAssociationWithProducts( |
||
937 | |||
938 | /** |
||
939 | * @param string $element |
||
940 | * @param string $value |
||
941 | */ |
||
942 | private function assertElementValue($element, $value) |
||
959 | |||
960 | /** |
||
961 | * @param string $element |
||
962 | * @param string $message |
||
963 | */ |
||
964 | private function assertValidationMessage($element, $message) |
||
978 | } |
||
979 |
PHP provides two ways to mark string literals. Either with single quotes
'literal'
or with double quotes"literal"
. The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (
\'
) and the backslash (\\
). Every other character is displayed as is.Double quoted string literals may contain other variables or more complex escape sequences.
will print an indented:
Single is Value
If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.
For more information on PHP string literals and available escape sequences see the PHP core documentation.