Beispiel #1
0
/**
 * 2015-02-04
 * Обратите внимание, что вряд ли мы вправе кэшировать результат при парметре $store = null,
 * ведь текущий магазин может меняться.
 * @param int|string|null|bool|StoreInterface $store [optional]
 * @return StoreInterface|Store
 * @throws \Magento\Framework\Exception\NoSuchEntityException|Exception
 * https://github.com/magento/magento2/issues/2222
 */
function df_store($store = null)
{
    /** @var StoreInterface $result */
    $result = $store;
    if (is_null($result)) {
        /**
         * 2015-11-04
         * По аналогии с @see \Magento\Store\Model\StoreResolver::getCurrentStoreId()
         * https://github.com/magento/magento2/blob/f578e54e093c31378ca981cfe336f7e651194585/app/code/Magento/Store/Model/StoreResolver.php#L82
         */
        /** @var string|null $storeCode */
        $storeCode = df_request(\Magento\Store\Model\StoreResolver::PARAM_NAME);
        if (is_null($storeCode)) {
            $storeCode = df_store_cookie_m()->getStoreCodeFromCookie();
        }
        if (is_null($storeCode)) {
            $storeCode = df_request('store-view');
        }
        /**
         * 2015-08-10
         * Доработал алгоритм.
         * Сначала мы смотрим, не находимся ли мы в административной части,
         * и нельзя ли при этом узнать текущий магазин из веб-адреса.
         * По аналогии с @see Mage_Adminhtml_Block_Catalog_Product_Grid::_getStore()
         *
         * 2015-09-20
         * При единственном магазине
         * вызываемый ниже метод метод @uses \Df\Core\State::getStoreProcessed()
         * возвратит витрину default, однако при нахождении в административной части
         * нам нужно вернуть витрину «admin».
         * Например, это нужно, чтобы правильно работала функция @used-by df_is_backend()
         * Переменная $coreCurrentStore в данной точке содержит витрину «admin».
         *
         * 2015-11-04
         * При нахождении в административном интерфейсе
         * и при отсутствии в веб-адресе идентификатора магазина
         * этот метод вернёт витрину по-умолчанию, а не витрину «admin».
         *
         * Не знаю, правильно ли это, то так делает этот метод в Российской сборке для Magento 1.x,
         * поэтому решил пока не менять поведение.
         *
         * В Magento 2 же стандартный метод \Magento\Store\Model\StoreManager::getStore()
         * при вызове без параметров возвращает именно витрину по умолчанию, а не витрину «admin»:
         * https://github.com/magento/magento2/issues/2254
         * «The call for \Magento\Store\Model\StoreManager::getStore() without parameters
         * inside the backend returns the default frontend store, not the «admin» store,
         * which is inconsistent with Magento 1.x behaviour and I think it will lead to developer mistakes.»
         */
        if (is_null($storeCode) && df_is_backend()) {
            $storeCode = df_request('store', 'admin');
        }
        if (!is_null($storeCode)) {
            $result = df_store_m()->getStore($storeCode);
        }
    }
    return is_object($result) ? $result : df_store_m()->getStore($result);
}
Beispiel #2
0
/**
* 2015-12-14
* Добавил возможность передачи в качестве первого параметра @see O
* причём как в виде объекта, так и строки-класса.
*
* Такая возможность позволяет нам эффективно рендерить шаблоны без иерархии своих классов-блоков.
* В Российской сборке для Magento 1.x
* нам приходилось дублировать один и тот же код в классе базовой модели (аналоге класса O),
* и в 2-х базовых классах блоков (абстрактном и блоке с шаблоном), т.е. в 3 местах.
* Теперь же нам этого делать не нужно.
*
* @used-by df_phtml()
* @param string|O|null $type
* @param string|array(string => mixed) $data [optional]
* @param string|null $template [optional]
*
* 2016-11-22
* @param array $vars [optional]
* Параметры $vars будут доступны в шаблоне в качестве переменных:
* @see \Magento\Framework\View\TemplateEngine\Php::render()
		extract($dictionary, EXTR_SKIP);
* https://github.com/magento/magento2/blob/2.1.2/lib/internal/Magento/Framework/View/TemplateEngine/Php.php#L58
*
* @return AbstractBlock|BlockInterface|Template
*/
function df_block($type, $data = [], $template = null, array $vars = [])
{
    /**
     * 2015-12-14
     * $type может быть как объектом, так и строкой:
     * https://3v4l.org/udMMH
     */
    /** @var O $context */
    if (!is_a($type, O::class, true)) {
        $context = null;
    } else {
        $context = is_object($type) ? $type : new $type();
        $type = null;
    }
    if (is_null($type)) {
        $type = df_is_backend() ? BackendTemplate::class : Template::class;
    }
    /** @var string|null $template */
    if (is_string($data)) {
        $template = $data;
        $data = [];
    }
    /** @var AbstractBlock|BlockInterface|Template $result */
    /**
     * 2016-11-22
     * В отличие от Magento 1.x, в Magento 2 нам нужен синтаксис ['data' => $data]:
     * @see \Magento\Framework\View\Layout\Generator\Block::createBlock():
     * $block->addData(isset($arguments['data']) ? $arguments['data'] : []);
     * https://github.com/magento/magento2/blob/2.1.2/lib/internal/Magento/Framework/View/Layout/Generator/Block.php#L240
     * В Magento 1.x было не так:
     * https://github.com/OpenMage/magento-mirror/blob/1.9.3.1/app/code/core/Mage/Core/Model/Layout.php#L482-L491
     */
    $result = df_layout()->createBlock($type, dfa($data, 'name'), ['data' => $data]);
    // 2016-11-22
    $result->assign($vars);
    if ($template && $result instanceof Template) {
        $result->setTemplate(df_append($template, '.phtml'));
    }
    if ($context) {
        // 2016-11-22
        // «Sets the object that should represent $block in template.»
        $result->setTemplateContext($context);
    }
    return $result;
}
Beispiel #3
0
 /**
  * 2015-09-27
  * Цель метода — получение информации о формировании в данный момент заголовка страницы.
  * @uses \Magento\Framework\View\Page\Title::get()
  * @param Sb $sb
  * @param \Closure $proceed
  * @return string
  */
 public function aroundGet(Sb $sb, \Closure $proceed)
 {
     df_state()->renderingTitle(true);
     try {
         $result = $proceed();
         /**
          * Делаем браузерные заголовки административной части
          * более короткими и понятными: оставляем лишь первую и последнюю части заголовка.
          */
         if (df_is_backend()) {
             /** @var string[] $resultA */
             $resultA = explode(Sb::TITLE_GLUE, $result);
             $result = 3 > count($resultA) ? $result : implode(Sb::TITLE_GLUE, [df_first($resultA), df_last($resultA)]);
         }
     } finally {
         df_state()->renderingTitle(false);
     }
     return $result;
 }
Beispiel #4
0
 /**
  * 2015-11-19
  * https://mage2.pro/t/228
  * «Propose to add a fieldset-specific element renderer»
  * @override
  * @param string $elementId
  * @param string $type
  * @param array $config
  * @param bool|false $after
  * @param bool|false $isAdvanced
  * @return AE
  */
 public function addField($elementId, $type, $config, $after = false, $isAdvanced = false)
 {
     /** @var AE $result */
     $result = parent::addField($elementId, $type, $config, $after, $isAdvanced);
     /** @var RendererInterface|null $renderer */
     $renderer = $this->getElementRendererDf();
     if (!$renderer && df_is_backend()) {
         /**
          * 2015-11-22
          * По аналогии с https://github.com/magento/magento2/blob/2.0.0/app/code/Magento/Backend/Block/Widget/Form.php#L70-L75
          * https://mage2.pro/t/239
          * @uses \Magento\Backend\Block\Widget\Form\Renderer\Fieldset\Element
          */
         $renderer = \Df\Backend\Block\Widget\Form\Renderer\Fieldset\Element::s();
     }
     if ($renderer) {
         $result->setRenderer($renderer);
     }
     return $result;
 }
Beispiel #5
0
 /**
  * 2016-02-15
  * @override
  * How is a payment method's isAvailable() used? https://mage2.pro/t/721
  *
  * @see \Magento\Payment\Model\MethodInterface::isAvailable()
  * https://github.com/magento/magento2/blob/6ce74b2/app/code/Magento/Payment/Model/MethodInterface.php#L343-L350
  * @see \Magento\Payment\Model\Method\AbstractMethod::isAvailable()
  * https://github.com/magento/magento2/blob/6ce74b2/app/code/Magento/Payment/Model/Method/AbstractMethod.php#L805-L825
  *
  * @param CartInterface|Q $quote [optional]
  * @return bool
  */
 public function isAvailable(CartInterface $quote = null)
 {
     /** @var bool $result */
     $result = ($this->availableInBackend() || !df_is_backend()) && $this->isActive($quote ? $quote->getStoreId() : null);
     if ($result) {
         /** @var DataObject $checkResult */
         $checkResult = new DataObject(['is_available' => true]);
         df_dispatch('payment_method_is_active', ['result' => $checkResult, 'method_instance' => $this, 'quote' => $quote]);
         $result = $checkResult['is_available'];
     }
     if ($result && $quote) {
         /** @var float $amount */
         $amount = $this->s()->cFromBase($quote->getBaseGrandTotal(), $quote);
         /** @var int|float $min */
         /** @var int|float $max */
         list($min, $max) = dfa($this->amountLimits(), $this->s()->currencyC($quote), [null, null]);
         $result = (is_null($min) || $amount >= $min) && (is_null($max) || $amount <= $max);
     }
     return $result;
 }
Beispiel #6
0
 /**
 * 2016-08-17
 * Цель плагина — форматирование внешнего вида платёжного адреса в том случае,
 * когда отключенен запрос этого адреса у покупателей, и данные, вероятно, пусты.
 *
 * Раньше я пробовал реализовать эту функциональность обработкой события «customer_address_format»:
 * https://github.com/mage2pro/core/blob/1.6.16/Customer/Observer/AddressFormat.php?ts=4#L37-L92
 * Однако такой подход оказался невозможен,
 * потому что метод @see \Magento\Sales\Model\Order\Address\Renderer::format() выглядит так:
 *
 		$formatType = $this->addressConfig->getFormatByCode($type);
 		if (!$formatType || !$formatType->getRenderer()) {
 			return null;
 		}
 		$this->eventManager->dispatch('customer_address_format', [
 		'type' => $formatType, 'address' => $address
 	]);
 		return $formatType->getRenderer()->renderArray($address->getData());
 *
 * Во-первых, надо обратить внимание, что $formatType — это одиночка.
 * 1) Сначала я наивно пытался её модифицировать, но тогда, раз это одиночка,
 * то мои изменения применялись ко всем последующим адресам,
 * в том числе к непустым адресам и адресам доставки.
 * 2) Второй попыткой было в обработчике события подменять одиночку $formatType на свой объект.
 * Но ведь метод @see \Magento\Sales\Model\Order\Address\Renderer::format() игнорирует
 * результат обработчика события, и продолжает использовать одиночку,
 * так что в таком подходе толку нет.
 *
 * Поэтому пришлось делать этот плагин.
 *
 * @see \Magento\Sales\Model\Order\Address\Renderer::format()
 * @param Sb $sb
 * @param \Closure $proceed
 * @param Address $a
 * @param string $type
 * @return string
 */
 public function aroundFormat(Sb $sb, \Closure $proceed, Address $a, $type)
 {
     /** @var string $result */
     // 2016-08-17
     // Убеждаемся, что firstname и lastname равны null,
     // чтобы не ломать отображение адресов, для которых информация присутствует
     // (например, эти адреса могли быть собраны до отключения опции askForBillingAddress).
     if (df_address_is_billing($a) && !$a->getFirstname() && !$a->getLastname()) {
         /** @var OP|null $payment */
         $payment = $a->getOrder()->getPayment();
         if ($payment && dfp_is_my($payment)) {
             /**
              * 2016-08-17
              * Раньше тут было ещё условие !$method->s()->askForBillingAddress(),
              * но на самом деле оно ошибочно,
              * потому что если администратор сначала отключил опцию askForBillingAddress,
              * собраз заказы, а потом снова включил эту опцию,
              * то адреса заказов, собранных во время отключения опции,
              * должны обрабатываться корректно.
              */
             /**
              * 2016-08-17
              * Дальнейший код идёт по аналалогии с кодом
              * @see \Magento\Sales\Model\Order\Address\Renderer::format()
              */
             /**
              * 2016-07-27
              * По аналогии с @see \Magento\Sales\Model\Order\Address\Renderer::format()
              * https://github.com/magento/magento2/blob/2.0.0/app/code/Magento/Sales/Model/Order/Address/Renderer.php#L51
              * @var DataObject $typeO
              */
             $typeO = $this->addressConfig()->getFormatByCode($type);
             /**
              * 2016-07-27
              * Если в будущем мы захотим написать что-либо более объёмное,
              * то можно поставить ещё 'escape_html' => false
              */
             $typeO->addData(['default_format' => __(!df_is_backend() ? 'Not used.' : 'The customer was not asked for it.')]);
             /** @var RendererInterface|DefaultRenderer|null $renderer */
             /** @noinspection PhpUndefinedCallbackInspection */
             $renderer = call_user_func([$typeO, 'getRenderer']);
             if (!$renderer) {
                 $result = null;
             } else {
                 df_dispatch('customer_address_format', ['type' => $typeO, 'address' => $a]);
                 $result = $renderer->renderArray($a->getData());
             }
         }
     }
     return isset($result) ? $result : $proceed($a, $type);
 }
Beispiel #7
0
 /**
  * 2016-08-20
  * @return bool
  */
 protected function isFrontend()
 {
     return !df_is_backend();
 }