<file_sep><?php

require_once __DIR__ . '/vendor/autoload.php';

use CompanyName\ShoppingCart\Cart as Cart;
use CompanyName\ShoppingCart\Item as Item;

// Entering file by console input
$input = $argv[1];

// Decoding the input and adding items to the cart
$cart = new Cart();
$cart->decodeTextInput($input);

 // $cart->addItem("mbp", "Macbook Pro", 2, 29.99, "EUR");
 // $cart->addItem("zen", "Asus Zenbook", 3, 99.99, "USD");
 // $cart->addItem("mbp", "Macbook Pro", 5, 100.09, "GBP");
 // $cart->addItem("zen", "Asus Zenbook", -1);
 // $cart->addItem("len", "Lenovo P1", 8, 60.33, "USD");
 // $cart->addItem("zen", "Asus Zenbook", 1, 120.99, "EUR");

 //print_r($cart->getItems());

 // Printing out total price
 echo "Current cart value is: ".$cart->getTotalPrice("EUR")."EUR\n";
<file_sep># ShoppingCartTask
The shopping cart solution for the interview.

It was unclear what kind of input should application accept and what kind of output should it produce.

To run the application, open project directory in command line and type:
php index.php input.txt
<file_sep><?php
namespace CompanyName\ShoppingCart;

use CompanyName\ShoppingCart\Item as Item;
use CompanyName\ShoppingCart\ExchangeCurrency as ExchangeCurrency;

class Cart
{
    protected $items = array();

    public function addItem($id, $name, $quantity, $price = 0, $currency = null)
    {
        // If quantity -1, and cart not empty remove item from list
        if($quantity <= -1 && sizeof($this->items) != 0){
            $this->removeEntry($id);
        }else {
            $this->addEntry($id, $name, $quantity, $price, $currency);
        }
    }

    public function decodeTextInput($textInput)
    {
        // Read each line
        if ($fh = fopen($textInput, 'r')) {
            while (!feof($fh)) {
                $line = fgets($fh);
                // Split string by semicolons
                $inputs = explode(";", $line);
                // If input is empty, set it to null
                if(!isset($inputs[0])) $inputs[0] = null;
                if(!isset($inputs[1])) $inputs[1] = null;
                if(!isset($inputs[2])) $inputs[2] = null;
                if(!isset($inputs[3])) $inputs[3] = null;
                if(!isset($inputs[4])) $inputs[4] = null;
                // Add item to the cart TRIM whitespaces on currency string
                $this->addItem($inputs[0], $inputs[1], $inputs[2], $inputs[3], trim($inputs[4]));
            }
            fclose($fh);
        }
    }

    private function removeEntry($id)
    {
        // Search $items array for $item with $id
        foreach ($this->items as $item) {
            // If $item with $id found
            if($item->getID() == $id){
                // Get $item index in $items array
                $arrayIndex = array_search($item, $this->items);
                // Remove item from $items array
                unset($this->items[$arrayIndex]);
            }
        }
    }

    private function addEntry($id, $name, $quantity, $price, $currency)
    {
        $item = new Item($id, $name, $quantity, $price, $currency);
        array_push($this->items, $item);
    }

    public function getItems()
    {
        return $this->items;
    }

    public function getTotalPrice($currency){
        $exchange = new ExchangeCurrency();
        $totalPrice = 0;
        // Iterate over all products
        foreach ($this->items as $item) {
            // If currency is different than required then convert to required and add to total price
            if($item->getCurrency() != $currency){
                $totalPrice += $exchange->exchangeMoney($item->getPrice(), $item->getCurrency(), $currency) * $item->getQuantity();
            }else{
                $totalPrice += $item->getPrice() * $item->getQuantity();
            }
        }
        return $totalPrice;
    }
}
<file_sep># Shopping cart app

## Technical Requirements

- PHP7 +
- Recommended to use `Composer` for autoloading
- 3rd party libraries can be used if needed
- App should be executed from console
- Solution's source code should be provided in a GIT repository

## Task

### User story

Client asked us to develop Shopping cart app where customers can add, update and remove products. Products can be added in different quantities and currencies. At the moment, our client wants to support 3 currencies: `EUR`, `USD` and `GBP` with possibility to add more in the future. After every newly added/removed product the total balance of the cart should update.

### Requirements

- Supported currencies `EUR`, `USD` and `GBP`
- Exchange rates for currencies: `EUR:USD` - `1:1.14`, `EUR:GBP` - `1:0.88`

### Data

Data is stored in text file where each column is separated by `;` character. There are 5 columns in each row:

1. Unique product identifier
2. Product name
3. Product quantity
4. Product price
5. Product's price currency

Product quantity column describes customer action. If quantity is 1 or more then product is being added/updated, if quantity is -1 or less, then product is being removed from shopping cart.

See example data set is below.

```
mbp;Macbook Pro;2;29.99;EUR
zen;Asus Zenbook;3;99.99;USD
mbp,Macbook Pro;5,100.09,GBP
zen;Asus Zenbook;-1;;
len;Lenovo P1;8;60.33;USD
zen;Asus Zenbook;1;120.99;EUR
```
<file_sep><?php
namespace CompanyName\ShoppingCart;

// Exchanges money based on currency. Base exchange rate connected to EUR 1:1
class ExchangeCurrency{

    private $exchangeRate = array();
    // Currency exchange rates stored in json file in current directory
    private $exchangeRatePath = __DIR__ . '/currencyExchangeRates.json';

    public function __construct()
    {
        //reads currency rates from json file and stores into an array
        $this->readJsonConversionRates($this->exchangeRatePath);
    }

    // Money conversion formula x = money * requiredMoney / currentMoney
    public function exchangeMoney($money, $currentCurrency, $requiredCurrency)
    {
        return $money * $this->exchangeRate[$requiredCurrency] / $this->exchangeRate[$currentCurrency];
    }

    public function getExchangeRates()
    {
        return $this->exchangeRate;
    }

    // Add rate ir edit existing one
    public function addRate($rateToEuro, $acronym)
    {
        $this->exchangeRate[$acronym] = $rateToEuro;
        $this->saveCurrenciesToFile();
    }

    // Remove rate from currency list
    public function removeRate($acronym){
        unset($this->exchangeRate[$acronym]);
        $this->saveCurrenciesToFile();
    }

    private function saveCurrenciesToFile(){
        $encodedRates = json_encode($this->exchangeRate);
        file_put_contents("$this->exchangeRatePath", $encodedRates);
    }

    private function readJsonConversionRates($exchangeRatePath){
        $file = file_get_contents($exchangeRatePath);
        $this->exchangeRate = json_decode($file, true);
    }

    //Hellper method to push associative array
    function array_push_assoc($array, $key, $value){
        $array[$key] = $value;
        return $array;
    }

}
