Ejemplo n.º 1
0
 /**
  * 2016-04-10
  * It is implemented by analogy with @see \Magento\Backend\Model\Auth::login()
  * https://github.com/magento/magento2/blob/052e789/app/code/Magento/Backend/Model/Auth.php#L137-L182
  *
  * @param string $email
  * @return void
  * @throws \Magento\Framework\Exception\AuthenticationException
  */
 public function loginByEmail($email)
 {
     $this->_initCredentialStorage();
     /** @var \Magento\Backend\Model\Auth\Credential\StorageInterface|\Magento\User\Model\User $user */
     $user = $this->getCredentialStorage();
     $user->{\Df\User\Plugin\Model\User::LOGIN_BY_EMAIL} = true;
     $user->login($email, null);
     if ($user->getId()) {
         /** @var \Magento\Backend\Model\Auth\StorageInterface|\Magento\Backend\Model\Auth\Session $authSession */
         $authSession = $this->getAuthStorage();
         $authSession->setUser($user);
         $authSession->processLogin();
         //$cookieManager->setSensitiveCookie($session->getName(), session_id());
         $_COOKIE[$authSession->getName()] = session_id();
         /** @var SessionManagerInterface|\Magento\Backend\Model\Session $session */
         $session = df_o(SessionManagerInterface::class);
         $session->setData(\Magento\Framework\Data\Form\FormKey::FORM_KEY, df_request('form_key'));
         df_dispatch('backend_auth_user_login_success', ['user' => $user]);
         /**
          * 2016-04-10
          * Обязательно, иначе авторизация работать не будет.
          * https://mage2.pro/t/1199
          */
         /** @var SecurityPlugin $securityPlugin */
         $securityPlugin = df_o(SecurityPlugin::class);
         $securityPlugin->afterLogin($this);
     }
 }
Ejemplo n.º 2
0
 /**
  * @param Sb $sb
  * @param \Closure $proceed
  * @param string $username
  * @param string $password
  * @return bool
  * @throws \Magento\Framework\Exception\AuthenticationException
  */
 public function aroundAuthenticate(Sb $sb, \Closure $proceed, $username, $password)
 {
     /** @var bool $loginByEmail */
     $loginByEmail = dfo($sb, self::LOGIN_BY_EMAIL);
     unset($sb->{self::LOGIN_BY_EMAIL});
     /** @var bool $result */
     $result = false;
     if ($loginByEmail) {
         /**
          * 2016-04-10
          * It is implemented by analogy with @see \Magento\User\Model\User::loadByUsername()
          * https://github.com/magento/magento2/blob/052e789/app/code/Magento/User/Model/User.php#L606-L619
          */
         /** @var array(string => mixed)|false $data */
         $data = Resource::s()->loadByEmail($username);
         if ($data) {
             $sb->setData($data);
             $result = true;
             df_dispatch('admin_user_authenticate_after', ['username' => $username, 'password' => null, 'user' => $sb, 'result' => $result]);
         }
     }
     return $result ? $result : $proceed($username, $password);
 }
Ejemplo n.º 3
0
 /**
 * 2016-07-28
 * Цель плагина — предоставление программистам удобной возможности
 * модификации коллекции $result, которая служит источником данных для таблиц.
 *
 * @see \Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider::getSearchResult()
 * https://github.com/magento/magento2/blob/2.1.0/lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/DataProvider.php#L308-L316
 *
 * Статьи по теме:
 * «How are the rows data retrieved for the backend's orders grid?» https://mage2.pro/t/1907
 * «How is @see \Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider::searchResultToOutput() implemented?»
 * https://mage2.pro/t/1908
 * «How is the «Payment Method» column implemented for the backend's orders grid?»
 * https://mage2.pro/t/1906
 *
 * Обратите внимание, что мы могли вместо плагина
 * перекрыть класс конкретной коллекции, например:
 * https://github.com/magento/magento2/blob/2.1.0/app/code/Magento/Sales/etc/di.xml#L768
 		<type name='Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory'>
 			<arguments>
 				<argument name='collections' xsi:type='array'>
 					<item name='sales_order_grid_data_source' xsi:type='string'
 					>Df\Sales\Model\ResourceModel\Order\Grid\Collection</item>
 				</argument>
 			</arguments>
 		</type>
 * Однако у такого подхода 2 недостатка:
 * 1) он неуниверсален и каждую конкретную коллекцию надо перекрывать отдельно.
 * 2) он хрупок: другие программисты могут захотеть перекрыть ту же коллекцию.
 *
 * Наш подход намного лучше.
 *
 * @param Sb $sb
 * @param SearchResultInterface|ApiSearchResult|UiSearchResult $result
 * @return string
 */
 public function afterGetSearchResult(Sb $sb, SearchResultInterface $result)
 {
     df_dispatch('df_data_provider__search_result', [self::PROVIDER => $sb, self::RESULT => $result]);
     return $result;
 }
Ejemplo n.º 4
0
 /**
  * 2016-07-28
  * Цель плагина — возбуждение события «df_column__prepare».
  * @see \Magento\Ui\Component\Listing\Columns\Column::prepare()
  * @param Sb $sb
  * @return void
  */
 public function beforePrepare(Sb $sb)
 {
     df_dispatch('df_column__prepare', [self::COLUMN => $sb]);
 }
Ejemplo n.º 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;
 }
Ejemplo n.º 6
0
 /**
  * 2015-12-07
  * Цель плагина — поддержка события «df_controller_front_send_response_after».
  * https://mage2.pro/t/288
  * Incosistency: the event «controller_front_send_response_after» is removed from Magento 2,
  * but the event «controller_front_send_response_before» is left.
  * https://mage2.pro/t/287
  * @see \Magento\Persistent\Observer\SynchronizePersistentInfoObserver
  * is subscribed on the absent event «controller_front_send_response_after»,
  * and so it is never called.
  * @see ResponseInterface::sendResponse()
  * @param Sb $sb
  * @param int|void $result
  * @return int|void
  */
 public function afterSendResponse(Sb $sb, $result)
 {
     df_dispatch('df_controller_front_send_response_after');
     return $result;
 }
Ejemplo n.º 7
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);
 }
Ejemplo n.º 8
0
 /**
  * 2015-10-12
  * Регистрация нового клиента.
  * @param MC $customer
  * @return void
  */
 private function register(MC $customer)
 {
     /**
      * 2015-10-12
      * https://github.com/magento/magento2/issues/2087
      * Приходится присваивать магазин в 2 шага...
      */
     /** @var \Magento\Store\Api\Data\StoreInterface|\Magento\Store\Model\Store $store */
     $store = df_store_m()->getStore();
     $customer->setStore($store);
     $customer->setGroupId(df_customer_group_m()->getDefaultGroup($store->getId())->getId());
     $customer->addData($this->customerData());
     $customer->save();
     /**
      * 2016-06-05
      * Не всегда имеет смысл автоматически создавать адрес.
      * В частности, для Amazon решил этого не делать,
      * потому что автоматический адрес создаётся на основании геолокации, что не точно,
      * а в случае с Amazon мы гарантированно можем получить точный адрес из профиля Amazon,
      * поэтому нам нет никакого смысла забивать систему неточным автоматическим адресом.
      * @see \Dfe\AmazonLogin\Controller\Index\Index::needCreateAddress()
      */
     if ($this->needCreateAddress()) {
         /** @var Address $address */
         $address = df_om()->create(Address::class);
         $address->setCustomer($customer);
         $address->addData(df_clean($this->addressData() + ['firstname' => $this->c()->nameFirst(), 'lastname' => $this->c()->nameLast(), 'middlename' => $this->c()->nameMiddle(), 'city' => df_visitor()->city(), 'country_id' => df_visitor()->iso2(), 'is_default_billing' => 1, 'is_default_shipping' => 1, 'postcode' => df_visitor()->postCode() ?: (df_is_postcode_required(df_visitor()->iso2()) ? '000000' : null), 'region' => df_visitor()->regionName(), 'region_id' => null, 'save_in_address_book' => 1, 'street' => '---', 'telephone' => '000000']));
         $address->save();
     }
     df_dispatch('customer_register_success', ['account_controller' => $this, 'customer' => $customer]);
 }