HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/SBogers10/shop.komma.nl/app/Discounts/DiscountService.php
<?php declare(strict_types=1);


namespace App\Discounts;


use App\Discounts\Conditions\AbstractDiscountConditionHandler;
use App\Vat\VatService;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;

class DiscountService
{
    private DiscountConditionService $discountConditionService;
    private DiscountActionService $discountActionService;
    private DiscountTranslationService $discountTranslationService;
    private Collection $discounts;
    private VatService $vatService;

    /**
     * DiscountService constructor.
     */
    public function __construct()
    {
        $this->discounts = $this->baseQuery()->get();
        $this->discountConditionService = new DiscountConditionService();
        $this->discountActionService = new DiscountActionService();
        $this->discountActionService = new DiscountActionService();
        $this->discountTranslationService = new DiscountTranslationService();
        $this->vatService = new VatService();
    }

    /**
     * Determines which discounts should be applied to the given discountable.
     *
     * @param DiscountableInterface $discountable
     * @return Collection
     */
    public function applyDiscountsTo(DiscountableInterface $discountable) {
        $discountable->clearDiscounts();
        $applicableDiscounts = $this->getApplicableDiscounts($discountable, $this->discounts);
        $this->applyDiscountActionsTo($applicableDiscounts, $discountable);
        return $applicableDiscounts;
    }

    /**
     * @param Discount[]|Collection            $applicableDiscounts
     * @param DiscountableInterface $discountable\
     */
    private function applyDiscountActionsTo(Collection $applicableDiscounts, DiscountableInterface $discountable) {
        foreach($applicableDiscounts as $applicableDiscount) {
            foreach($applicableDiscount->actions as $discountAction) {
                $handler = $this->discountActionService->makeHandler($discountAction->type);

                $handler->apply($discountable, $this->vatService, $applicableDiscount->translation->title, $discountAction->params);
            }
        }
    }

    private function getApplicableDiscounts(DiscountableInterface $discountable, Collection $discounts): Collection {
        /** @var Collection|Discount[] $discounts */
        /** @var AbstractDiscountConditionHandler[]|Collection $discountConditionHandlers */
        $stoppedProcessing = false;

        $applicableDiscounts = $discounts->filter(function (Discount $discount) use($discountable, &$stoppedProcessing) {
            //Check if we may must process this discount
            if($stoppedProcessing) return false;

            //Get the conditions of the discount which are applicable
            $applicableConditions = $discount->conditions->filter(function(DiscountCondition $discountCondition) use($discountable) {
                $handler = $this->discountConditionService->makeHandler($discountCondition->type);
                return $handler->canBeApplied($discountable, $discountCondition->operator, $discountCondition->params);
            });

            //Filter out discounts of which not all conditions are met.
            $allConditionsAreMet = $applicableConditions->count() === $discount->conditions->count();

            //Check if we need to stop processing next discounts if all conditions where met.
            if($allConditionsAreMet && $discount->stop_processing) {
                $stoppedProcessing = true;
            }

            return $allConditionsAreMet;
        });

        return $applicableDiscounts;
    }

    public function saveFromJsonArray(array $data) {
        if(!array_key_exists('state', $data)) return new Discount();

        $discount = null;
        switch ($data['state']) {
            case Discount::NEW:
                $discount = new Discount();
                $discount->fill($data);
                $discount->save();
                if(array_key_exists('actions', $data)) $this->discountActionService->saveFromJsonArray($discount, $data['actions']);
                if(array_key_exists('conditions', $data)) $this->discountConditionService->saveFromJsonArray($discount, $data['conditions']);
                if(array_key_exists('translations', $data)) $this->discountTranslationService->saveFromJsonArray($discount, $data['translations']);
                break;
            case Discount::PRISTINE:
            case Discount::DIRTY:
                /** @var Discount $discount */
                $discount = Discount::with('translations', 'conditions', 'actions')->find($data['id']);
                $discount->fill($data);
                $discount->save();
                if(array_key_exists('actions', $data)) $this->discountActionService->saveFromJsonArray($discount, $data['actions']);
                if(array_key_exists('conditions', $data)) $this->discountConditionService->saveFromJsonArray($discount, $data['conditions']);
                if(array_key_exists('translations', $data)) $this->discountTranslationService->saveFromJsonArray($discount, $data['translations']);
                break;
            case Discount::DELETED:
                $discount = Discount::find($data['id']);
                if(!$discount) throw new \InvalidArgumentException('Data refers to a discount that does not exist anymore. Cannot delete discount');
                $this->deleteDiscount($discount);
                break;
        }

        return $discount;
    }

    private function deleteDiscount(Discount $discount) {
        $discount->translations()->delete();
        $discount->actions()->delete();
        $discount->conditions()->delete();
        $discount->delete();
    }

    /**
     * @param $sortOrderData
     * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
     */
    public function updateSortOrder($sortOrderData)
    {
        if(!is_array($sortOrderData)) abort(400, 'Expected the request to have a property of type array with name "sortOrderData", but did not get that');

        $discounts = $this->baseQuery()->get();

        foreach ($sortOrderData as $orderId => $sortOrder) {
            $discount = $discounts->where('id', '=', $orderId)->first();
            $discount->sort_order = $sortOrder;
            $discount->save();
        }

        return $this->baseQuery()->get();
    }

    /**
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function baseQuery()
    {
        return Discount::with('translations.language', 'translation.language', 'conditions', 'actions')->orderBy('sort_order', 'asc');
    }

    /**
     * @return array|mixed
     */
    public function weatherInfo()
    {
        try {
            $data = Cache::remember('buienradarWeerData', 3600, function () {
                return file_get_contents('https://data.buienradar.nl/2.0/feed/json');
            });

            $data = json_decode($data, true);
            if($data === null) return null;
            return $data;
        } catch (\Exception $exception) {
            return [];
        }
    }
}