Your IP : 127.0.0.1


Current Path : /home/dev2.destoffenstraat.com/app/code/Swissup/DeliveryDate/Helper/
Upload File :
Current File : /home/dev2.destoffenstraat.com/app/code/Swissup/DeliveryDate/Helper/Data.php

<?php

namespace Swissup\DeliveryDate\Helper;

use Magento\Store\Model\ScopeInterface;
use Magento\Framework\Stdlib\DateTime\DateTime;
use Magento\Framework\Intl\DateTimeFactory;
use Swissup\DeliveryDate\Model\Config\Source\FirstAvailableDay;

class Data extends \Magento\Framework\App\Helper\AbstractHelper
{
    const CONFIG_ENABLED                    = 'delivery_date/main/enabled';
    const CONFIG_FILTER_PER_SHIPPING_METHOD = 'delivery_date/main/filter_per_shipping_method';
    const CONFIG_SHIPPING_METHODS           = 'delivery_date/main/shipping_methods';

    const CONFIG_DATE_LABEL             = 'delivery_date/main/field_label';
    const CONFIG_DATE_USE_DEFAULT_VALUE = 'delivery_date/main/date_use_default_value';
    const CONFIG_DATE_SHOW              = 'delivery_date/main/date_show';
    const CONFIG_DATE_FORMAT            = 'delivery_date/main/date_format';
    const CONFIG_DATE_FIRSTDAY          = 'general/locale/firstday';

    const CONFIG_TIME_LABEL             = 'delivery_date/main/time_label';
    const CONFIG_TIME_SHOW              = 'delivery_date/main/time_show';
    const CONFIG_TIME_OPTIONS           = 'delivery_date/main/time_options';

    const CONFIG_PROCESSING_END_TIME    = 'delivery_date/first_available/processing_end_time';
    const CONFIG_PROCESSING_END_TIME_EXCEPTIONS = 'delivery_date/first_available/processing_end_time_exceptions';
    const CONFIG_FIRST_DAY              = 'delivery_date/first_available/first_day';
    const CONFIG_MIN_DELAY              = 'delivery_date/first_available/min_delay';
    const CONFIG_MAX_DELAY              = 'delivery_date/last_available/max_delay';
    const CONFIG_EXCLUDE_WEEKDAYS       = 'delivery_date/exclude/exclude_weekdays';
    const CONFIG_HOLIDAYS               = 'delivery_date/exclude/holidays';

    /**
     * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface
     */
    public $timeZone;

    /**
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    public $storeManager;

    /**
     * @var DateTimeFactory
     */
    private $dateTimeFactory;

    /**
     * @var \Magento\Config\Model\Config\Backend\Serialized\ArraySerializedFactory
     */
    private $serializedArrayFactory;

    /**
     * @param \Magento\Framework\App\Helper\Context $context
     * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $timeZone
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param DateTimeFactory $dateTimeFactory
     */
    public function __construct(
        \Magento\Framework\App\Helper\Context $context,
        \Magento\Framework\Stdlib\DateTime\TimezoneInterface $timeZone,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        DateTimeFactory $dateTimeFactory,
        \Magento\Config\Model\Config\Backend\Serialized\ArraySerializedFactory $serializedArrayFactory
    ) {
        $this->timeZone = $timeZone;
        $this->storeManager = $storeManager;
        $this->dateTimeFactory = $dateTimeFactory;
        $this->serializedArrayFactory = $serializedArrayFactory;
        return parent::__construct($context);
    }

    /**
     * @param  string $key
     * @param  string $scope
     * @return string
     */
    protected function getOption($key, $scope = ScopeInterface::SCOPE_STORE)
    {
        return $this->scopeConfig->getValue($key, $scope);
    }

    /**
     * @param  string $key
     * @param  string $scope
     * @return array
     */
    protected function unserializeOption($key, $scope = ScopeInterface::SCOPE_STORE)
    {
        $model = $this->serializedArrayFactory->create()->setValue($this->getOption($key, $scope));

        $model->afterLoad();

        return $model->getValue() ?: [];
    }

    /**
     * @return bool
     */
    public function isEnabled()
    {
        return (bool) $this->getOption(self::CONFIG_ENABLED);
    }

    /**
     * @return bool
     */
    public function isFilterPerShippingMethod()
    {
        // for some reason config option means the opposite (💩), so use ! to get what we want...
        return (bool) !$this->getOption(self::CONFIG_FILTER_PER_SHIPPING_METHOD);
    }

    /**
     * @return string
     */
    public function getShippingMethods()
    {
        return (string) $this->getOption(self::CONFIG_SHIPPING_METHODS);
    }

    /**
     * @return int
     */
    public function getMaxDelayDays()
    {
        return (int) $this->getOption(self::CONFIG_MAX_DELAY);
    }

    /**
     * @return array
     */
    public function getExcludedWeekdays()
    {
        $config = $this->getOption(self::CONFIG_EXCLUDE_WEEKDAYS);

        if (!$config && !is_numeric($config)) {
            return [];
        }

        return array_map('intval', explode(',', $config));
    }

    /**
     * @return string
     */
    public function getDateLabel()
    {
        return $this->getOption(self::CONFIG_DATE_LABEL);
    }

    /**
     * @return string
     */
    public function getDateStatus()
    {
        return $this->getOption(self::CONFIG_DATE_SHOW);
    }

    /**
     * @param string $shippingMethod
     * @return bool
     */
    public function isDateRequired($shippingMethod = null)
    {
        if ($shippingMethod && $this->isFilterPerShippingMethod()) {
            $methods = explode(',', $this->getShippingMethods());
            if (!in_array($shippingMethod, $methods)) {
                return false;
            }
        }
        return $this->getDateStatus() === 'req';
    }

    /**
     * @return bool
     */
    public function useDefaultDateValue()
    {
        return (bool) $this->getOption(self::CONFIG_DATE_USE_DEFAULT_VALUE);
    }

    /**
     * @return string
     */
    public function getFirstDay()
    {
        return $this->getOption(self::CONFIG_DATE_FIRSTDAY);
    }

    /**
     * @return string
     */
    public function getTimeLabel()
    {
        return $this->getOption(self::CONFIG_TIME_LABEL);
    }

    /**
     * @return string
     */
    public function getTimeStatus()
    {
        return $this->getOption(self::CONFIG_TIME_SHOW);
    }

    /**
     * @param string $shippingMethod
     * @return bool
     */
    public function isTimeRequired($shippingMethod = null)
    {
        if ($shippingMethod && $this->isFilterPerShippingMethod()) {
            $methods = explode(',', $this->getShippingMethods());
            if (!in_array($shippingMethod, $methods)) {
                return false;
            }
        }
        return $this->getTimeStatus() === 'req';
    }

    /**
     * @return string
     */
    public function getTimeOptions($valuesOnly = false)
    {
        $values = $this->unserializeOption(self::CONFIG_TIME_OPTIONS);
        if (!$values) {
            return [];
        }

        $result = [
            [
                'value' => '',
                'label' => __('Please Select'),
            ],
        ];
        foreach ($values as $value) {
            $label = sprintf(
                '%s:%s — %s:%s',
                $value['from']['hour'],
                $value['from']['minute'],
                $value['to']['hour'],
                $value['to']['minute']
            );
            $result[] = [
                'value' => $label,
                'label' => $label,
            ];
        }

        if ($valuesOnly) {
            $result = array_column($result, 'value');
        }

        return $result;
    }

    /**
     * @return int
     */
    public function getMinDelayDays()
    {
        $result = 0;

        // move to the next day if processing time is up
        $time = $this->getOption(self::CONFIG_PROCESSING_END_TIME);
        list($hour, $minute, $second) = explode(',', $time);

        $now = new \DateTime();
        $weekday = $now->format('w');
        $exceptions = $this->unserializeOption(self::CONFIG_PROCESSING_END_TIME_EXCEPTIONS);

        foreach ($exceptions as $exception) {
            if ($exception['weekday'] === $weekday) {
                $hour = $exception['time']['hour'];
                $minute = $exception['time']['minute'];

                break;
            }
        }

        $endOfProcessingDay = new \DateTime();
        $endOfProcessingDay->setTime($hour, $minute, $second);

        if ($now >= $endOfProcessingDay) {
            $now->add(new \DateInterval('P1D'));
            $result++;
        }

        // move to the next day if today is holiday
        if ($this->getOption(self::CONFIG_FIRST_DAY) === FirstAvailableDay::DAY_BUSINESS) {
            $limit = 60;
            $now->setTime(0, 0, 0, 0);
            while ($this->isDayOff($now) && $limit-- > 0) {
                $now->add(new \DateInterval('P1D'));
                $result++;
            }
        }

        // apply delivery date offset config
        $result += (int) $this->getOption(self::CONFIG_MIN_DELAY);

        return $result;
    }

    /**
     * @param string $date
     * @return boolean
     */
    public function isValid($date)
    {
        if (!$date) {
            return true;
        }

        $date = new \DateTime($date);
        $now = new \DateTime();
        $now->setTime(0, 0, 0, 0);
        $minDelay = $this->getMinDelayDays();
        $interval = $now->diff($date);

        if ($interval->invert || $interval->days < $minDelay) {
            return false;
        }

        return !$this->isDayOff($date);
    }

    /**
     * Check if supplied date is a holiday of a weekend.
     *
     * @param \DateTime $date
     * @return boolean
     */
    protected function isDayOff($date)
    {
        // weekend
        $excludedDays = $this->getExcludedWeekdays();
        $weekday = $date->format('w');
        if (in_array($weekday, $excludedDays)) {
            return true;
        }

        // holidays
        $holidays = $this->getHolidays();
        $timestamp = $date->getTimestamp() * 1000;
        if (in_array($timestamp, $holidays)) {
            return true;
        }

        return false;
    }

    /**
     * @param  string $dateString
     * @param  string|false $format
     * @return string|false
     */
    public function formatMySqlDateTime($dateString, $format = false)
    {
        if (!$dateString) {
            return false;
        }

        $format = $format ? $format : $this->getDateFormat();
        $dateTime = \DateTime::createFromFormat($format, $dateString);
        if ($dateTime) {
            $format = \Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT;
            $dateTime->setTime(0, 0, 0);
            $dateTime = $dateTime->format($format);
        }

        return $dateTime;
    }

    /**
     * @param string $date
     * @return string
     */
    public function getFormattedDate($date)
    {
        if (!$date) {
            return '';
        }

        $date = $this->dateTimeFactory->create($date);
        $dateFormat = $this->getDateFormat();
        $date = $date->format($dateFormat);
        return $date;
    }

    /**
     * @return mixed
     */
    public function getDateFormat($forJsCalendar = false)
    {
        $format = $this->getOption(self::CONFIG_DATE_FORMAT);

        if (empty($format)) {
            $format = $this->timeZone->getDateFormatWithLongYear();
        }

        // convert pattern to date format:
        //  dd.MM.Y => d.m.Y (uk_UA) and so on
        $mapping = [
            'dd' => 'd',
            // 'M' => 'm', // don't use literal monthes (Arabic locale fix)
            // 'F' => 'm', // don't use literal monthes (Arabic locale fix)
            'MM' => 'm',
            'yyyy' => 'Y',  // @see mage/calendar.js#430
            'yy' => 'Y',    // @see mage/calendar.js#430
            'y' => 'Y',     // @see mage/calendar.js#430
            'G' => '',      // ar_SA locale returns pattern with era: 'd‏/M‏/y GGGGG'
        ];
        $format = str_replace(array_keys($mapping), $mapping, $format);

        // strip right-to-left marker as it brakes input value
        $format = preg_replace('/(\x{200e}|\x{200f})/u', '', $format);

        if ($forJsCalendar) {
            $mapping = [
                'm' => 'mm',
                'M' => 'MMM',   // Jan through Dec.          @see mage/calendar.js#424
                'F' => 'MMMM',  // January through December. @see mage/calendar.js#423
                'd' => 'dd',    // 01 to 31
                'j' => 'd',     // 1 to 31
                'l' => 'EEEE',  // Sunday through Saturday. @see mage/calendar.js#418
                'D' => 'EEE',   // Sun through Sat.         @see mage/calendar.js#419
                'z' => 'o',     // 0 through 365
            ];
            $format = str_replace(array_keys($mapping), $mapping, $format);
        }

        return trim($format);
    }

    /**
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     *
     * @param  array   $years
     * @param  array   $months
     * @param  array   $days
     * @param  integer $offset
     * @return array of timestamps
     */
    protected function timestamps($years = [], $months = [], $days = [], $offset = 1)
    {
        if (0 == $years) {
            $_year = date("Y");
            $years = range($_year - 1, $_year + 6);
        }
        if (!is_array($years)) {
            $years = [$years];
        }
        if (0 == $months) {
            $months = range(1, 12);
        }
        if (!is_array($months)) {
            $months = [$months];
        }
        if (!is_array($days)) {
            $days = [$days];
        }
        $offset = (int) $offset;
        $result = [];
        foreach ($years as $year) {
            foreach ($months as $month) {
                foreach ($days as $day) {
                    for ($i = 0; $i < $offset; $i++) {
                        $result[] = strtotime(
                            $year  . '-' . $month . '-' . $day . ' 00:00+00:00 +' . $i . ' days'
                        ) * 1000;
                    }
                }
            }
        }
        return $result;
    }

    /**
     * @return array
     */
    public function getHolidays()
    {
        $_holidays = $this->unserializeOption(self::CONFIG_HOLIDAYS);
        if (!$_holidays) {
            return [];
        }

        $holidays = [];
        foreach ($_holidays as $_h) {
            if (isset($_h['day']) && isset($_h['month']) && isset($_h['year'])) {
                $offset = isset($_h['offset']) && 0 != $_h['offset'] ? $_h['offset'] : 1;
                $holidays = array_merge($holidays, $this->timestamps(
                    $_h['year'],
                    $_h['month'],
                    $_h['day'],
                    $offset
                ));
            }
        }
        $holidays = array_filter($holidays);
        $holidays = array_unique($holidays);
        return $holidays;
    }
}