diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..0a2ab674 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.idea +vendor +.env +dbdata diff --git a/README.md b/README.md index 6490de86..aaf128bb 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ -# PHP2021 \ No newline at end of file +# PHP2021 + +https://otus.ru/lessons/razrabotchik-php/?utm_source=github&utm_medium=free&utm_campaign=otus diff --git a/code/app.php b/code/app.php new file mode 100644 index 00000000..289e1685 --- /dev/null +++ b/code/app.php @@ -0,0 +1,11 @@ +run(); +} +catch(Exception $e) { + App\Response::generateBadRequestResponse($e->getMessage()); +} \ No newline at end of file diff --git a/code/app/Adapters/KitchenAdapter.php b/code/app/Adapters/KitchenAdapter.php new file mode 100644 index 00000000..b4a32b2a --- /dev/null +++ b/code/app/Adapters/KitchenAdapter.php @@ -0,0 +1,46 @@ +kitchenService = $kitchenService; + } + + /** + * @param MealInterface $meal + * @return void + * @throws Exception + */ + public function cookMeal(MealInterface $meal): void + { + $currentIngredients = $meal->getIngredients(); + $meal->resetIngredients(); + $meal->addIngredients($this->kitchenService->fry($currentIngredients)); + + if ($this->kitchenService->checkMealQuality($meal)) { + $meal->setStatus('Cooked and checked'); + } else { + throw new Exception('Cooking failed'); + } + } + + /** + * @param MealInterface $meal + * @return void + */ + public function utilizeMeal(MealInterface $meal): void + { + $this->kitchenService->utilize($meal); + } +} \ No newline at end of file diff --git a/code/app/Adapters/KitchenService.php b/code/app/Adapters/KitchenService.php new file mode 100644 index 00000000..24c0a3a4 --- /dev/null +++ b/code/app/Adapters/KitchenService.php @@ -0,0 +1,55 @@ + $value) { + if (in_array($ingredient, self::$needFried)) { + $cookedIngredients["fried_{$ingredient}"] = $value; + } else { + $cookedIngredients[$ingredient] = $value; + } + } + + return $cookedIngredients; + } + + /** + * @param MealInterface $meal + * @return bool + */ + public function checkMealQuality(MealInterface $meal): bool + { + foreach ($meal->getIngredients() as $ingredient => $value) + if (in_array($ingredient, self::$needFried)) return false; + return true; + } + + /** + * @param MealInterface $meal + * @return void + */ + public function utilize(MealInterface $meal): void + { + $meal->setStatus('Utilized'); + } +} \ No newline at end of file diff --git a/code/app/Application.php b/code/app/Application.php new file mode 100644 index 00000000..252338f6 --- /dev/null +++ b/code/app/Application.php @@ -0,0 +1,54 @@ +request = RequestValidator::validate($_POST); + } catch (Exception $e) { + throw new Exception($e->getMessage()); + } + } + + /** + * @return void + * @throws Exception + */ + public function run(): void + { + $customer = new Customer(); + $order = new OrderContext($customer); + + switch ($_POST['meal']) { + case 'Burger': + $order->setCookingStrategy(new BurgerStrategy()); + break; + case 'HotDog': + $order->setCookingStrategy(new HotDogStrategy()); + break; + case 'Sandwich': + $order->setCookingStrategy(new SandwichStrategy()); + break; + default: + throw new Exception('No meal choosed'); + } + + $meal = $order->getOrderedMeal($_POST['client_ingredients'] ?? []); + print_r($meal->getIngredients()); + } +} \ No newline at end of file diff --git a/code/app/Decorators/BurgerDecorator.php b/code/app/Decorators/BurgerDecorator.php new file mode 100644 index 00000000..f513f3e1 --- /dev/null +++ b/code/app/Decorators/BurgerDecorator.php @@ -0,0 +1,36 @@ + 3, + 'onion' => 2, + 'lettuce' => 1, + 'cotlete' => 1, + ]; + + /** + * @param MealDecorator $mealBaseClass + * @return void + */ + public function __constructor(MealDecorator $mealBaseClass): void + { + $this->mealDecorator = $mealBaseClass; + } + + /** + * @return void + */ + public function addBaseIngredients(): void + { + $this->mealDecorator->ingredients = array_merge( + $this->mealDecorator->ingredients, + $this->mealDecorator->getAdapter()->addIngredients(self::$baseRecipe) + ); + $this->mealDecorator->setStatus('Added base burger recipe ingredients'); + } +} \ No newline at end of file diff --git a/code/app/Decorators/CustomerIngredientsDecorator.php b/code/app/Decorators/CustomerIngredientsDecorator.php new file mode 100644 index 00000000..f13d0efa --- /dev/null +++ b/code/app/Decorators/CustomerIngredientsDecorator.php @@ -0,0 +1,34 @@ +mealDecorator = $mealBaseClass; + } + + /** + * @param array $customerIngredients + * @return void + */ + public function addCustomerIngredients(array $customerIngredients): void + { + $this->mealDecorator->ingredients = array_merge( + $this->mealDecorator->ingredients, + $this->mealDecorator->getAdapter()->addIngredients($customerIngredients) + ); + $this->mealDecorator->setStatus('Added client Ingredients'); + } + + +} \ No newline at end of file diff --git a/code/app/Decorators/HotDogDecorator.php b/code/app/Decorators/HotDogDecorator.php new file mode 100644 index 00000000..e40ccfd1 --- /dev/null +++ b/code/app/Decorators/HotDogDecorator.php @@ -0,0 +1,36 @@ + 1, + 'mustard' => 1, + 'sausage' => 1, + ]; + + /** + * @param MealBaseClass $mealBaseClass + * @return void + */ + public function __constructor(MealBaseClass $mealBaseClass): void + { + $this->mealDecorator = $mealBaseClass; + } + + /** + * @return void + */ + public function addBaseIngredients(): void + { + $this->mealDecorator->ingredients = array_merge( + $this->mealDecorator->ingredients, + $this->mealDecorator->getAdapter()->addIngredients(self::$baseRecipe) + ); + $this->mealDecorator->setStatus('Added base hot-dog recipe ingredients'); + } +} \ No newline at end of file diff --git a/code/app/Decorators/MealDecorator.php b/code/app/Decorators/MealDecorator.php new file mode 100644 index 00000000..c6a0d520 --- /dev/null +++ b/code/app/Decorators/MealDecorator.php @@ -0,0 +1,76 @@ +mealBaseClass = $mealBaseClass; + $this->adapter = new IngredientAdapter(); + $this->resetIngredients(); + } + + /** + * @return void + */ + public function resetIngredients(): void + { + $this->ingredients = $this->mealBaseClass->getIngredients(); + } + + /** + * @param string $status + * @return void + */ + public function setStatus(string $status): void + { + $this->mealBaseClass->setStatus($status); + } + + /** + * @return string + */ + public function getBaseType(): string + { + return get_class($this->mealBaseClass); + } + + /** + * @return array + */ + public function getIngredients(): array + { + return $this->ingredients; + } + + /** + * @param array $ingredients + * @return void + */ + public function addIngredients(array $ingredients = []): void + { + $this->ingredients = array_merge($this->ingredients, $ingredients); + } + + /** + * @return IngredientAdapter + */ + public function getAdapter(): IngredientAdapter + { + return $this->adapter; + } +} \ No newline at end of file diff --git a/code/app/Decorators/SandwichDecorator.php b/code/app/Decorators/SandwichDecorator.php new file mode 100644 index 00000000..5935de9f --- /dev/null +++ b/code/app/Decorators/SandwichDecorator.php @@ -0,0 +1,35 @@ + 1, + 'cheese' => 2, + ]; + + /** + * @param MealBaseClass $mealBaseClass + * @return void + */ + public function __constructor(MealBaseClass $mealBaseClass): void + { + $this->mealDecorator = $mealBaseClass; + } + + /** + * @return void + */ + public function addBaseIngredients(): void + { + $this->mealDecorator->ingredients = array_merge( + $this->mealDecorator->ingredients, + $this->mealDecorator->getAdapter()->addIngredients(self::$baseRecipe) + ); + $this->mealDecorator->setStatus('Added base sandwich recipe ingredients'); + } +} \ No newline at end of file diff --git a/code/app/Factories/BurgerFactory.php b/code/app/Factories/BurgerFactory.php new file mode 100644 index 00000000..eafb2af4 --- /dev/null +++ b/code/app/Factories/BurgerFactory.php @@ -0,0 +1,13 @@ +setIngredients([ + new Ingredient('bread'), + new Ingredient('cutlet',2), + new Ingredient('cheese',3), + new Ingredient('lettuce leaf'), + new Ingredient('tomato slice'), + new Ingredient('sauce'), + new Ingredient('cucumber slice'), + ]); + } + +} \ No newline at end of file diff --git a/code/app/Meals/HotDog.php b/code/app/Meals/HotDog.php new file mode 100644 index 00000000..d85385be --- /dev/null +++ b/code/app/Meals/HotDog.php @@ -0,0 +1,17 @@ +setIngredients([ + new Ingredient('bread'), + new Ingredient('sausage'), + new Ingredient('sauce'), + new Ingredient('carrot') + ]); + } +} \ No newline at end of file diff --git a/code/app/Meals/Ingredient.php b/code/app/Meals/Ingredient.php new file mode 100644 index 00000000..e3e97734 --- /dev/null +++ b/code/app/Meals/Ingredient.php @@ -0,0 +1,37 @@ +name = $name; + $this->amount = $amount; + } + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @return int + */ + public function getAmount(): int + { + return $this->amount; + } + + +} \ No newline at end of file diff --git a/code/app/Meals/IngredientAdapter.php b/code/app/Meals/IngredientAdapter.php new file mode 100644 index 00000000..48ba0c2d --- /dev/null +++ b/code/app/Meals/IngredientAdapter.php @@ -0,0 +1,21 @@ + $amount) + { + $arrObjectIngredients[] = new Ingredient($ingredient, (int) $amount); + } + + return $arrObjectIngredients; + } +} \ No newline at end of file diff --git a/code/app/Meals/MealBaseClass.php b/code/app/Meals/MealBaseClass.php new file mode 100644 index 00000000..eb3337c4 --- /dev/null +++ b/code/app/Meals/MealBaseClass.php @@ -0,0 +1,95 @@ +objectStorage = new SplObjectStorage(); + } + + /** + * @return array + */ + public function getIngredients(): array + { + return $this->ingredients; + } + + /** + * @param SplObserver $observer + * @return void + */ + public function attach(SplObserver $observer): void + { + $this->objectStorage->attach($observer); + } + + /** + * @param SplObserver $observer + * @return void + */ + public function detach(SplObserver $observer): void + { + $this->objectStorage->detach($observer); + } + + /** + * @return void + */ + public function notify(): void + { + foreach ($this->objectStorage as $item) { + $item->update($this); + } + } + + /** + * @param string $status + * @return void + */ + public function setStatus(string $status): void + { + $this->status = $status; + $this->notify(); + } + + /** + * @return string + */ + public function getStatus(): string + { + return $this->status; + } + + /** + * @param array $ingredients + * @return void + */ + public function setIngredients(array $ingredients = []): void + { + $this->ingredients = $ingredients; + } + + /** + * @param array $ingredients + * @return void + */ + public function addIngredients(array $ingredients = []): void + { + $this->ingredients = array_merge($this->ingredients, $ingredients); + } + +} \ No newline at end of file diff --git a/code/app/Meals/MealInterface.php b/code/app/Meals/MealInterface.php new file mode 100644 index 00000000..299e8671 --- /dev/null +++ b/code/app/Meals/MealInterface.php @@ -0,0 +1,11 @@ +setIngredients([ + new Ingredient('bread'), + new Ingredient('sauce'), + new Ingredient('sausage slices',20), + new Ingredient('cheese'), + ]); + } +} \ No newline at end of file diff --git a/code/app/Observers/Customer.php b/code/app/Observers/Customer.php new file mode 100644 index 00000000..a7f5d250 --- /dev/null +++ b/code/app/Observers/Customer.php @@ -0,0 +1,18 @@ +getStatus(); + } +} \ No newline at end of file diff --git a/code/app/RequestValidator.php b/code/app/RequestValidator.php new file mode 100644 index 00000000..734d5710 --- /dev/null +++ b/code/app/RequestValidator.php @@ -0,0 +1,43 @@ +generateBaseBurger(); + $baseBurger->attach($customer); + $baseBurger->setStatus('Started'); + return $this->addIngredients($baseBurger, $ingredients); + } + + /** + * @return MealInterface + */ + private function generateBaseBurger(): MealInterface + { + $factory = new BurgerFactory(); + return $factory->createMealBase(); + } + + /** + * @param MealInterface $meal + * @param array $customerIngredients + * @return MealInterface + */ + private function addIngredients(MealInterface $meal, array $customerIngredients): MealInterface + { + $decorator = new MealDecorator($meal); + $burgerDecorator = new BurgerDecorator($decorator); + $burgerDecorator->addBaseIngredients(); + $customerDecorator = new CustomerIngredientsDecorator($decorator); + $customerDecorator->addCustomerIngredients($customerIngredients); + + return $decorator; + } +} \ No newline at end of file diff --git a/code/app/Strategies/CookingStrategyInterface.php b/code/app/Strategies/CookingStrategyInterface.php new file mode 100644 index 00000000..4f8e3c32 --- /dev/null +++ b/code/app/Strategies/CookingStrategyInterface.php @@ -0,0 +1,16 @@ +generateBaseHotDog(); + $baseHotDog->attach($customer); + $baseHotDog->setStatus('Started'); + return $this->addIngredients($baseHotDog, $ingredients); + } + + /** + * @return MealInterface + */ + private function generateBaseHotDog(): MealInterface + { + return (new HotDogFactory())->createMealBase(); + } + + /** + * @param MealInterface $meal + * @param array $customerIngredients + * @return MealInterface + */ + private function addIngredients(MealInterface $meal, array $customerIngredients): MealInterface + { + $decorator = new MealDecorator($meal); + $hotDogDecorator = new HotDogDecorator($decorator); + $hotDogDecorator->addBaseIngredients(); + $customerDecorator = new CustomerIngredientsDecorator($decorator); + $customerDecorator->addCustomerIngredients($customerIngredients); + + return $decorator; + } +} \ No newline at end of file diff --git a/code/app/Strategies/OrderContext.php b/code/app/Strategies/OrderContext.php new file mode 100644 index 00000000..d628d509 --- /dev/null +++ b/code/app/Strategies/OrderContext.php @@ -0,0 +1,53 @@ +customer = $customer; + } + + /** + * @param CookingStrategyInterface $strategy + * @return void + */ + public function setCookingStrategy(CookingStrategyInterface $strategy): void + { + $this->strategy = $strategy; + } + + /** + * @param array $ingredients + * @return MealInterface + */ + public function getOrderedMeal(array $ingredients = []): MealInterface + { + $orderedMeal = $this->strategy->prepareIngredients($ingredients, $this->customer); + $orderedMeal->setStatud('Preparations'); + + try { + $kitchen = new KitchenAdapter(new KitchenService()); + $kitchen->cookMeal($orderedMeal); + } catch (Exception $e) { + if ($kitchen instanceof KitchenAdapter) { + $kitchen->utilizeMeal($orderedMeal); + } + } + + return $orderedMeal; + } +} \ No newline at end of file diff --git a/code/app/Strategies/SandwichStrategy.php b/code/app/Strategies/SandwichStrategy.php new file mode 100644 index 00000000..dd8959cc --- /dev/null +++ b/code/app/Strategies/SandwichStrategy.php @@ -0,0 +1,47 @@ +generateBaseSandwich(); + $baseSandwich->attach($customer); + $baseSandwich->setStatus('Started'); + return $this->addIngredients($baseSandwich, $ingredients); + + } + + /** + * @return MealInterface + */ + private function generateBaseSandwich(): MealInterface + { + return (new SandwichFactory())->createMealBase(); + } + + /** + * @param MealInterface $meal + * @param array $customerIngredients + * @return MealInterface + */ + private function addIngredients(MealInterface $meal, array $customerIngredients): MealInterface + { + $decorator = new MealDecorator($meal); + $sandwichDecorator = new SandwichDecorator($decorator); + $sandwichDecorator->addBaseIngredients(); + $customerDecorator = new CustomerIngredientsDecorator($decorator); + $customerDecorator->addCustomerIngredients($customerIngredients); + + return $decorator; + } +} \ No newline at end of file diff --git a/code/composer.json b/code/composer.json new file mode 100644 index 00000000..76f50cd2 --- /dev/null +++ b/code/composer.json @@ -0,0 +1,12 @@ +{ + "require": { + "php": ">=7.4", + "ext-json": "*", + "ext-sockets": "*" + }, + "autoload": { + "psr-4": { + "App\\": "app" + } + } +} \ No newline at end of file