Ejemplo n.º 1
0
 /**
  * 2016-03-26
  * Ситуация, когда платёж не найден, является нормальной,
  * потому что к одной учётной записи Stripe может быть привязано несколько магазинов,
  * и Stripe будет оповещать сразу все магазины о событиях одного из них.
  * Магазину надо уметь различать свои события и чужие,
  * и мы делаем это именно по идентификатору транзакции.
  * @return Payment|DfPayment|null
  */
 public function payment()
 {
     return dfc($this, function () {
         /** @var int|null $id */
         $id = df_fetch_one('sales_payment_transaction', 'payment_id', ['txn_id' => $this->id()]);
         return !$id ? null : df_load(Payment::class, $id);
     });
 }
Ejemplo n.º 2
0
 /**
  * 2016-06-04
  * @return \DateTime|null
  */
 public function dob()
 {
     return dfc($this, function () {
         /** @var \DateTime|null $result */
         $result = $this->_dob();
         if (!$result && df_is_customer_attribute_required('dob')) {
             $result = new \DateTime();
             $result->setDate(1900, 1, 1);
         }
         return $result;
     });
 }
Ejemplo n.º 3
0
 /**
  * 2016-07-31
  * @param string $class
  * @return Settings
  */
 protected function child($class)
 {
     return dfc($this, function ($class) {
         /**
          * 2015-08-04
          * Ошибочно писать здесь self::s($class)
          * потому что класс ребёнка не обязательно должен быть наследником класса родителя:
          * ему достаточно быть наследником @see \Df\Config\Settings
          * @var Settings $result
          */
         $result = df_sc($class, __CLASS__);
         $result->setScope($this->scope());
         return $result;
     }, func_get_args());
 }
Ejemplo n.º 4
0
Archivo: O.php Proyecto: mage2pro/core
 /**
  * 2016-08-10
  * @param callable $f
  * @param mixed|null $d [optional]
  * @param string|null $key [optional]
  * @return mixed
  */
 private function filter(callable $f, $d = null, $key = null)
 {
     return dfc($this, function ($f, $d, $key) {
         return call_user_func($f, $this->v($d, $key));
     }, [$f, $d, $key ?: df_caller_f(1)]);
 }
Ejemplo n.º 5
0
 /**
  * 2016-08-20
  * @return T|null
  */
 protected function transL()
 {
     return dfc($this, function () {
         return df_trans_by_payment_last($this->ii());
     });
 }
Ejemplo n.º 6
0
 /**
  * 2016-07-10
  * @return string
  */
 public function asText()
 {
     return dfc($this, function () {
         return df_cc_n($this->asArray());
     });
 }
Ejemplo n.º 7
0
 /**
  * 2016-11-12
  * @override
  * @see \Df\Payment\ConfigProvider::s()
  * @return S
  */
 protected function s()
 {
     return dfc($this, function () {
         return df_ar(parent::s(), S::class);
     });
 }
Ejemplo n.º 8
0
 /**
  * 2015-12-07
  * 2016-01-01
  * Сегодня заметил, что Magento 2, в отличие от Magento 1.x,
  * допускает иерархическую вложенность групп настроек большую, чем 3, например:
  * https://github.com/magento/magento2/blob/2.0.0/app/code/Magento/Cron/etc/adminhtml/system.xml#L14
  * В Magento 1.x вложенность всегда такова: section / group / field.
  * В Magento 2 вложенность может быть такой: section / group / group / field.
  * @return array(string => mixed)
  */
 protected function value()
 {
     return dfc($this, function () {
         /** @var string[] $pathA */
         $pathA = array_slice(df_explode_xpath($this->getPath()), 1);
         /** @var string $fieldName */
         $fieldName = array_pop($pathA);
         /** @var string $path */
         $path = 'groups/' . implode('/groups/', $pathA) . '/fields/' . $fieldName;
         /** @var array(string => mixed) $result */
         /**
          * 2016-09-02
          * При сохранении настроек вне области действия по умолчанию
          * в результат попадает ключ «inherit». Удаляем его.
          * https://code.dmitry-fedyuk.com/m2e/allpay/issues/24
          */
         $result = dfa_unset(dfa_deep($this->_data, $path), 'inherit');
         df_result_array($result);
         return $result;
     });
 }
Ejemplo n.º 9
0
 /**
  * 2016-07-10
  * @return Transaction
  */
 private function requestTransaction()
 {
     return dfc($this, function () {
         return df_load(Transaction::class, $this->requestIdG(), true, 'txn_id');
     });
 }
Ejemplo n.º 10
0
 /**
  * 2016-08-27
  * @return S
  */
 protected function s()
 {
     return dfc($this, function () {
         return S::convention($this);
     });
 }
Ejemplo n.º 11
0
 /** @return X */
 public function e()
 {
     return dfc($this, function () {
         return df_xml_parse($this[self::$P__E]);
     });
 }
Ejemplo n.º 12
0
 /**
  * 2016-09-07
  * Размер транзакции в платёжной валюте: «Mage2.PRO» → «Payment» → <...> → «Payment Currency».
  * @return float|int|string
  */
 protected final function amountF()
 {
     return dfc($this, function () {
         return $this->amountFormat($this->amount());
     });
 }
Ejemplo n.º 13
0
 /**
 * 2016-06-06
 * Цель плагина — устранение дефекта ядра, который проявляется в том,
 * что непосредственно после авторизации посетителя через какой-либо сторонний сервис
 * (в моих случаях: Facebook, Amazon) имя покупателя не отображается в шапке.
 * Это блок @see \Magento\Customer\Block\Account\Customer не имеет атрибута «cacheable»:
 * https://github.com/magento/magento2/blob/2.1.0-rc1/app/design/frontend/Magento/luma/Magento_Customer/layout/default.xml#L11
 *
 * Это разумно, потому что этот блок отображается на всех страницах витрины,
 * и он используется не только для авторизованных посетителей, но и для анонимных,
 * и если он будет «cacheable», то тогда полностраничное кэширование не будет работать вовсе.
 *
 * Однако из-за отсутствия атрибута «cacheable» система считает,
 * что она может кэшировать страницу целиком:
 * @see \Magento\Framework\View\Layout::isCacheable()
 * https://github.com/magento/magento2/blob/2.1.0-rc1/lib/internal/Magento/Framework/View/Layout.php#L1073-L1083
 		public function isCacheable()
 		{
 			$this->build();
 			$cacheableXml = !(bool)count($this->getXml()->xpath('//' . Element::TYPE_BLOCK . '[@cacheable="false"]'));
 			return $this->cacheable && $cacheableXml;
 		}
 * Это, в принципе, ещё тоже само по себе не смертельно, ведь блок работает через AJAX,
 * и по хорошему вполне бы мог корректно подгружать имя посетителя асинхронно
 * даже при полностью закэшированной странице.
 *
 * Однако коварный метод @see \Magento\PageCache\Model\Layout\LayoutPlugin::afterGenerateXml()
 * https://github.com/magento/magento2/blob/2.1.0-rc1/app/code/Magento/PageCache/Model/Layout/LayoutPlugin.php#L37-L51
 * видит, что isCacheable() вернуло true, и устанавливает заголовок «Сache-Сontrol: public»:
 *«Set appropriate Cache-Control headers. We have to set public headers in order to tell Varnish and Builtin app that page should be cached»:
 		 public function afterGenerateXml(\Magento\Framework\View\Layout $subject, $result)
 		 {
 			 if ($subject->isCacheable() && $this->config->isEnabled()) {
 				 $this->response->setPublicHeaders($this->config->getTtl());
 			 }
 			 return $result;
 		 }
 *
 * Непосвящённому программисту может быть ещё неочевидно, что здесь такого особенного.
 * Однако затем в дело вступает метод @see \Magento\Framework\App\PageCache\Kernel::process():
 * https://github.com/magento/magento2/blob/2.1.0-rc1/lib/internal/Magento/Framework/App/PageCache/Kernel.php#L65-L90
 * Он видит, что заголовок «Сache-Сontrol» начинается с «Сache-Сontrol: public»:
 * if (preg_match('/public.*s-maxage=(\d+)/', $response->getHeader('Cache-Control')->getFieldValue(), $matches))
 * ... и грохает все куки вызовом функции @see header_remove()
 		$response->clearHeader('Set-Cookie');
 		if (!headers_sent()) {
 			header_remove('Set-Cookie');
 		}
 * Тут уже ясно, что наступает пипец, но может быть ещё неочевидно, какой именно.
 * Пипец же в том, что в числе прочих грохается кука
 * @see \Magento\Customer\Model\Customer\NotificationStorage::UPDATE_CUSTOMER_SESSION
 * https://github.com/magento/magento2/blob/2.1.0-rc1/app/code/Magento/Customer/Model/Customer/NotificationStorage.php#L12
 *
 * Эта кука ранее была установлена методом
 * @see \Magento\Customer\Model\Plugin\CustomerNotification::beforeDispatch():
 * https://github.com/magento/magento2/blob/2.1.0-rc1/app/code/Magento/Customer/Model/Plugin/CustomerNotification.php#L70-L97
 *
 		if ($this->state->getAreaCode() == Area::AREA_FRONTEND
 			&& $this->notificationStorage->isExists(
 			NotificationStorage::UPDATE_CUSTOMER_SESSION,
 			$this->session->getCustomerId()
 		)) {
 		...
 			$publicCookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata();
 			$publicCookieMetadata->setDurationOneYear();
 			$publicCookieMetadata->setPath('/');
 			$publicCookieMetadata->setHttpOnly(false);
 			$this->cookieManager->setPublicCookie(
 				NotificationStorage::UPDATE_CUSTOMER_SESSION,
 				$this->session->getCustomerId(),
 				$publicCookieMetadata
 			);
 * В свою очередь, в notification storage ключ UPDATE_CUSTOMER_SESSION устанавливается
 * при сохранении покупателя:
 * @see \Magento\Customer\Model\ResourceModel\Customer::_afterSave()
 		protected function _afterSave(\Magento\Framework\DataObject $customer)
 		{
 			$this->getNotificationStorage()->add(
 				NotificationStorage::UPDATE_CUSTOMER_SESSION,
 				$customer->getId()
 			);
 			return parent::_afterSave($customer);
 		}
 * При авторизации покупателя через внешнюю систему мы как раз и делаем сохранение покупателя:
 * ведь мы получаем данные покупателя из внешней системы и их надо сохранить в Magento:
 * @see \Df\Sso\CustomerReturn::customer()
 * https://github.com/mage2pro/core/blob/4cd771d1/Customer/External/ReturnT.php?ts=4#L191
 *
 * Итак, куки грохаются, ключ «update_customer_session» из кук пропадает.
 * Что теперь происходит в браузере? Смотрим:
 		updateSession = $.cookieStorage.get('update_customer_session');
 		if (updateSession) {
 			mageStorage.post(
 				options.updateSessionUrl,
 				JSON.stringify({
 					'customer_id': updateSession,
 					'form_key': window.FORM_KEY
 				})
 			).done(
 				function() {
 					$.cookieStorage
 						.setConf({path: '/', expires: -1})
 						.set('update_customer_session', null)
 					;
 				}
 			);
 		}
 * Вот именно здесь браузер должен поддягивать свежую информацию о покупателе.
 * Но мы этого удовольствия лишены, потому что куки-то грохнуты.
 * Вот для исправления этой ситуации и предназначен мой метод.
 * @see \Magento\Framework\View\Layout::isCacheable()
 *
 * 2016-06-06
 * df_cookie_m()->getCookie(NotificationStorage::UPDATE_CUSTOMER_SESSION)
 * здесь нихуя не работает, потому что
 * @see \Magento\Framework\Stdlib\Cookie\PhpCookieReader::getCookie()
 * тупо смотрит в $_COOKIE (куки прошлого сеанса),
 * но не смотрит те новые куки, которые мы установили в этом сеансе.
 *
 * @param Sb $sb
 * @param int|void $result
 * @return int|void
 */
 public function afterIsCacheable(Sb $sb, $result)
 {
     return $result && !dfc($this, function () {
         return df_find(function ($h) {
             return df_starts_with($h, 'Set-Cookie: update_customer_session') || df_starts_with($h, 'Set-Cookie: ' . self::NEED_UPDATE_CUSTOMER_DATA);
         }, headers_list());
     });
 }
Ejemplo n.º 14
0
 /**
  * 2016-11-13
  * Поддержка фиксированного списка валют.
  * Используется модулем «Omise»:
  * https://code.dmitry-fedyuk.com/m2e/omise/blob/0.0.6/etc/adminhtml/system.xml#L154
  * При таком синтаксисе мы намеренно не добавляем в результат «Order Currency» и «Base Currency».
  * Метод будет возвращать только те значения из dfValues,
  * которые включены администратором в перечень разрешённых валют.
  * @return string[]
  */
 private function filter()
 {
     return dfc($this, function () {
         return df_fe_fc_csv($this, 'dfValues');
     });
 }
Ejemplo n.º 15
0
 /**
  * 2016-07-13
  * 2016-07-28
  * Транзакции может не быть в случае каких-то сбоев.
  * Решил не падать из-за этого, потому что мы можем попасть сюда
  * в невинном сценарии отображения таблицы заказов
  * (в контексте рисования колонки с названиями способов оплаты).
  * @return T|null
  */
 private function transParent()
 {
     return dfc($this, function () {
         return df_trans_by_payment_first($this->ii());
     });
 }
Ejemplo n.º 16
0
 /**
  * 2016-09-07
  * Намеренно не используем @see _storeId
  * @return Store
  */
 private function store()
 {
     return dfc($this, function () {
         return $this->o()->getStore();
     });
 }
Ejemplo n.º 17
0
 /**
  * 2016-05-06
  * @return array(string => string)
  */
 private function meta()
 {
     return dfc($this, function () {
         return Metadata::vars($this->store(), $this->o());
     });
 }
Ejemplo n.º 18
0
 /**
  * 2016-08-05
  * @return string
  */
 private function tag()
 {
     return dfc($this, function () {
         return strtolower($this[self::$P__TAG]);
     });
 }
Ejemplo n.º 19
0
 /**
  * 2016-05-30
  * @return bool
  */
 protected function thirdPartyLocalhost()
 {
     return dfc($this, function () {
         return df_is_localhost() && !df_my();
     });
 }
Ejemplo n.º 20
0
 /**
  * 2016-11-30
  * Другой алгоритм: $this->getParentBlock() instanceof Links
  *@used-by _toHtml()
  * @used-by loggedOut()
  * @return string
  */
 private function isInHeader()
 {
     return dfc($this, function () {
         return 'header.links' === df_parent_name($this);
     });
 }
Ejemplo n.º 21
0
 /**
  * 2016-08-27
  * @return T|null
  */
 private function t()
 {
     return dfc($this, function () {
         return df_trans_by_payment_last($this->p());
     });
 }
Ejemplo n.º 22
0
 /**
  * 2016-09-05
  * «Mage2.PRO» → «Payment» → <...> → «Payment Currency»
  * Текущая валюта может меняться динамически (в том числе посетителем магазина и сессией),
  * поэтому мы используем параметр store, а не scope
  * @param null|string|int|S|Store $s [optional]
  * @param Currency|string|null $oc [optional]
  * @return Currency
  */
 private function currency($s = null, $oc = null)
 {
     return dfc($this, function ($s = null, $oc = null) {
         return CurrencyFE::v($this->v('currency', $s), $s, $oc);
     }, func_get_args());
 }
Ejemplo n.º 23
0
 /**
  * 2016-08-14
  * @param string $class [optional]
  * @return EavSetup
  */
 protected final function sEav($class = EavSetup::class)
 {
     return dfc($this, function ($class) {
         return df_create($class, ['setup' => $this->s()]);
     }, [$class]);
 }
Ejemplo n.º 24
0
 /**
  * 2016-07-18
  * @return Settings
  */
 private function ss()
 {
     return dfc($this, function () {
         return $this->paymentMethod()->s();
     });
 }
Ejemplo n.º 25
0
 /**
  * 2016-06-04
  * @used-by mc()
  * @return string
  */
 private final function fId()
 {
     return dfc($this, function () {
         return Schema::fIdC($this);
     });
 }