├── .gitignore ├── main.php ├── tests └── GildedRose │ └── Tests │ └── GildedRoseTest.php ├── composer.json ├── phpunit.xml ├── src └── GildedRose │ ├── Item.php │ └── Program.php └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /main.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | tests/ 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/GildedRose/Item.php: -------------------------------------------------------------------------------- 1 | $v) { 14 | if (property_exists($this, $k)) { 15 | $this->$k = $v; 16 | } 17 | } 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gilded Rose Kata for PHP 2 | 3 | Port of the Gilded Rose Kata for C# (https://github.com/NotMyself/GildedRose) 4 | 5 | ## Install 6 | 7 | * Git Checkout: git clone https://github.com/qafoo/gilded-rose-kata 8 | * Generate Autoloader: composer dump-autoload 9 | * Run tests with "phpunit" 10 | 11 | ## Introduction 12 | 13 | Hi and welcome to team Gilded Rose. As you know, we are a small inn with a 14 | prime location in a prominent city ran by a friendly innkeeper named Allison. 15 | We also buy and sell only the finest goods. Unfortunately, our goods are 16 | constantly degrading in quality as they approach their sell by date. We have a 17 | system in place that updates our inventory for us. It was developed by a 18 | no-nonsense type named Leeroy, who has moved on to new adventures. Your task is 19 | to add the new feature to our system so that we can begin selling a new 20 | category of items. First an introduction to our system: 21 | 22 | - All items have a SellIn value which denotes the number of days we have to 23 | sell the item 24 | - All items have a Quality value which denotes how valuable the 25 | item is 26 | - At the end of each day our system lowers both values for every item 27 | 28 | Pretty simple, right? Well this is where it gets interesting: 29 | 30 | - Once the sell by date has passed, Quality degrades twice as fast 31 | - The Quality of an item is never negative 32 | - "Aged Brie" actually increases in Quality the older it gets 33 | - The Quality of an item is never more than 50 34 | - "Sulfuras", being a legendary item, never has to be sold or decreases in 35 | Quality 36 | - "Backstage passes", like aged brie, increases in Quality as it's 37 | SellIn value approaches; Quality increases by 2 when there are 10 days or less 38 | and by 3 when there are 5 days or less but Quality drops to 0 after the concert 39 | 40 | We have recently signed a supplier of conjured items. This requires an update 41 | to our system: 42 | 43 | - "Conjured" items degrade in Quality twice as fast as normal items 44 | 45 | Feel free to make any changes to the UpdateQuality method and add any new code 46 | as long as everything still works correctly. However, do not alter the Item 47 | class or Items property as those belong to the goblin in the corner who will 48 | insta-rage and one-shot you as he doesn't believe in shared code ownership (you 49 | can make the UpdateQuality method and Items property static if you like, we'll 50 | cover for you). Your work needs to be completed by Friday, February 18, 2011 51 | 08:00:00 AM PST. 52 | 53 | Just for clarification, an item can never have its Quality increase above 50, 54 | however "Sulfuras" is a legendary item and as such its Quality is 80 and it 55 | never alters. 56 | 57 | ## Task 58 | 59 | Start Refactoring this legacy code to emerge into a TDD design, keeping 60 | the requirements that are already covered by the project. Start 61 | implementing tests for the already known dependencies, then start refactoring 62 | the code to be SOLID. 63 | 64 | ## Complexity 65 | 66 | The GildedRose UpdateQuality() method has a very high complexity and is very 67 | useful to teach refactoring and testing of legacy code: 68 | 69 | - The method UpdateQuality() has a Cyclomatic Complexity of 19. The configured cyclomatic complexity threshold is 10. 70 | - The method UpdateQuality() has an NPath complexity of 211. The configured NPath complexity threshold is 200. 71 | 72 | -------------------------------------------------------------------------------- /src/GildedRose/Program.php: -------------------------------------------------------------------------------- 1 | "+5 Dexterity Vest",'sellIn' => 10,'quality' => 20)), 58 | new Item(array( 'name' => "Aged Brie",'sellIn' => 2,'quality' => 0)), 59 | new Item(array( 'name' => "Elixir of the Mongoose",'sellIn' => 5,'quality' => 7)), 60 | new Item(array( 'name' => "Sulfuras, Hand of Ragnaros",'sellIn' => 0,'quality' => 80)), 61 | new Item(array( 62 | 'name' => "Backstage passes to a TAFKAL80ETC concert", 63 | 'sellIn' => 15, 64 | 'quality' => 20 65 | )), 66 | new Item(array('name' => "Conjured Mana Cake",'sellIn' => 3,'quality' => 6)), 67 | )); 68 | 69 | $app->UpdateQuality(); 70 | 71 | echo sprintf("%50s - %7s - %7s\n", "Name", "SellIn", "Quality"); 72 | foreach ($app->items as $item) { 73 | echo sprintf("%50s - %7d - %7d\n", $item->name, $item->sellIn, $item->quality); 74 | } 75 | } 76 | 77 | public function __construct(array $items) 78 | { 79 | $this->items = $items; 80 | } 81 | 82 | public function UpdateQuality() 83 | { 84 | for ($i = 0; $i < count($this->items); $i++) { 85 | if ($this->items[$i]->name != "Aged Brie" && $this->items[$i]->name != "Backstage passes to a TAFKAL80ETC concert") { 86 | if ($this->items[$i]->quality > 0) { 87 | if ($this->items[$i]->name != "Sulfuras, Hand of Ragnaros") { 88 | $this->items[$i]->quality = $this->items[$i]->quality - 1; 89 | } 90 | } 91 | } else { 92 | if ($this->items[$i]->quality < 50) { 93 | $this->items[$i]->quality = $this->items[$i]->quality + 1; 94 | 95 | if ($this->items[$i]->name == "Backstage passes to a TAFKAL80ETC concert") { 96 | if ($this->items[$i]->sellIn < 11) { 97 | if ($this->items[$i]->quality < 50) { 98 | $this->items[$i]->quality = $this->items[$i]->quality + 1; 99 | } 100 | } 101 | 102 | if ($this->items[$i]->sellIn < 6) { 103 | if ($this->items[$i]->quality < 50) { 104 | $this->items[$i]->quality = $this->items[$i]->quality + 1; 105 | } 106 | } 107 | } 108 | } 109 | } 110 | 111 | if ($this->items[$i]->name != "Sulfuras, Hand of Ragnaros") { 112 | $this->items[$i]->sellIn = $this->items[$i]->sellIn - 1; 113 | } 114 | 115 | if ($this->items[$i]->sellIn < 0) { 116 | if ($this->items[$i]->name != "Aged Brie") { 117 | if ($this->items[$i]->name != "Backstage passes to a TAFKAL80ETC concert") { 118 | if ($this->items[$i]->quality > 0) { 119 | if ($this->items[$i]->name != "Sulfuras, Hand of Ragnaros") { 120 | $this->items[$i]->quality = $this->items[$i]->quality - 1; 121 | } 122 | } 123 | } else { 124 | $this->items[$i]->quality = $this->items[$i]->quality - $this->items[$i]->quality; 125 | } 126 | } else { 127 | if ($this->items[$i]->quality < 50) { 128 | $this->items[$i]->quality = $this->items[$i]->quality + 1; 129 | } 130 | } 131 | } 132 | } 133 | } 134 | } 135 | --------------------------------------------------------------------------------