/** * 2015-11-19 * @override * @see \Magento\Framework\Data\Form\Element\Renderer\RendererInterface::render() * @param AE|\Df\Framework\Form\Element $element * @return string */ public function render(AE $element) { /** @var bool $labelAtRight */ $labelAtRight = E::shouldLabelBeAtRight($element); /** * 2015-12-11 * Класс .df-label-sibling означает: элемент рядом с label. * В данном случае это всегда непосредственно элемент управления, * а вот для блочных элементов это может быть div-оболочка вокруг элемента: * @see \Df\Backend\Block\Widget\Form\Renderer\Fieldset\Element::elementHtml() */ $element->addClass('df-label-sibling'); /** * 2015-12-28 * К сожалению, мы не можем назначать классы для label: * @uses \Magento\Framework\Data\Form\Element\AbstractElement::getLabelHtml() * https://github.com/magento/magento2/blob/2.0.0/lib/internal/Magento/Framework/Data/Form/Element/AbstractElement.php#L425 * Потому ситуацию, когда label расположена справа от элемента, * помечаем классом для элемента. * При этом сама label справа может быть выбрана селектором .df-label-sibling ~ label */ if ($labelAtRight) { $element->addClass('df-label-at-right'); } /** @var string $innerA */ $innerA = [$element->getLabelHtml(), $element->getElementHtml()]; if ($labelAtRight) { $innerA = array_reverse($innerA); } return df_tag('span', ['class' => df_cc_s('df-element-inline', 'df-field', E::getClassDfOnly($element), $element->getContainerClass())], implode($innerA)); }
/** * 2016-09-03 * @override * Неправильно вызывать @uses df_fe_init() в методе * @see \Df\Framework\Form\Element\Select2::onFormInitialized(), * потому что onFormInitialized() вызывается на * @see \Df\Framework\Form\Element\Select2::setForm() * плагином @see \Df\Framework\Plugin\Data\Form\Element\AbstractElement::afterGetElementHtml() * https://github.com/mage2pro/core/blob/1.7.33/Framework/Plugin/Data/Form/Element/AbstractElement.php?ts=4#L77-L83 * и туда мы попадаем из метода @see \Magento\Config\Block\System\Config\Form::_initElement() * в точке https://github.com/magento/magento2/blob/2.1.1/app/code/Magento/Config/Block/System/Config/Form.php#L347-L367 * перед инициализацией опций выпадающего списка, * которая происходит в том же методепозже, в точке * https://github.com/magento/magento2/blob/2.1.1/app/code/Magento/Config/Block/System/Config/Form.php#L376-L378 * * Поэтому вызываем @uses df_fe_init() в методе @see \Df\Framework\Form\Element\Select2::setRenderer(), * который вызывается из метода @see \Magento\Config\Block\System\Config\Form::_initElement() * уже после инициализации опций выпадающего списка, в точке * https://github.com/magento/magento2/blob/2.1.1/app/code/Magento/Config/Block/System/Config/Form.php#L379 * * @see \Magento\Framework\Data\Form\Element\AbstractElement::setRenderer() * @used-by \Magento\Config\Block\System\Config\Form::_initElement() * https://github.com/magento/magento2/blob/2.1.1/app/code/Magento/Config/Block/System/Config/Form.php#L379 * @param IRenderer $renderer * @return $this */ public function setRenderer(IRenderer $renderer) { /** * 2016-09-03 * В первый раз мы попадаем сюда отсюда: * @see \Magento\Framework\Data\Form\Element\Fieldset::addField() * https://github.com/magento/magento2/blob/2.1.1/lib/internal/Magento/Framework/Data/Form/Element/Fieldset.php#L213 * В этот момент опции выпадающего списка ещё не инициализированы, * поэтому дожидаемся их инициализации. */ if (!isset($this->{__METHOD__}) && $this->getValues()) { /** * 2016-09-03 * Этот класс присваивается оригинальному элементу select * (который при использовании select2 вроде бы роли не играет), * и родительскому контейнеру .df-field, который присутствует в том случае, * если наш элемент управления был создан внутри нашего нестандартного филдсета, * и осутствует, если наш элемент управления является элементом управления вернхнего уровня * (то есть, указан в атрибуте «type» тега <field>). */ $this->addClass(df_cc_s('df-select2', $this->customCssClass())); df_fe_init($this, __CLASS__, df_asset_third_party('Select2/main.css'), ['cssClass' => df_cc_s('df-select2', $this->customCssClass(), Fieldset::customCssClassByShortName(df_fe_name_short($this->getName()))), 'options' => $this->getValues(), 'value' => $this->getValue(), 'width' => $this->width()]); $this->{__METHOD__} = true; } return parent::setRenderer($renderer); }
/** @return string */ private function openTagWithAttributesAsText() { return df_cc_s($this->tag(), $this->shouldAttributesBeMultiline() ? "\n" : null, call_user_func($this->shouldAttributesBeMultiline() ? 'df_tab_multiline' : 'df_nop', implode($this->shouldAttributesBeMultiline() ? "\n" : ' ', df_clean(df_map_k(function ($name, $value) { df_param_string_not_empty($name, 0); /** * 2015-04-16 * Передавать в качестве $value массив имеет смысл, например, для атрибута «class». * * 2016-11-29 * Не использую @see df_e(), чтобы сохранить двойные кавычки (data-mage-init) * и в то же время сконвертировать одинарные * (потому что значения атрибутов мы ниже обрамляем именно одинарными). */ $value = htmlspecialchars(str_replace("'", ''', !is_array($value) ? $value : df_cc_s($value)), ENT_NOQUOTES, 'UTF-8', false); return '' === $value ? '' : "{$name}='{$value}'"; }, $this->attributes()))))); }
/** * 2016-03-09 * @param O $order * @return string */ function df_order_customer_name(O $order) { /** @var string $result */ $result = df_cc_s($order->getCustomerFirstname(), $order->getCustomerMiddlename(), $order->getCustomerLastname()); if (!$result) { /** @var C $customer */ $customer = $order->getCustomer(); if ($customer) { $result = $customer->getName(); } } if (!$result) { /** @var OA|null $ba */ $ba = $order->getBillingAddress(); if ($ba) { $result = $ba->getName(); } } if (!$result) { /** @var OA|null $ba */ $sa = $order->getShippingAddress(); if ($sa) { $result = $sa->getName(); } } if (!$result) { /** * 2016-08-24 * Имени в адресах может запросто не быть * (например, если покупатель заказывает цифровой товар и askForBillingAddress = false), * и вот тогда мы попадаем сюда. * В данном случае функция вернёт просто «Guest». */ $result = $this->o()->getCustomerName(); } return $result; }
/** * 2015-12-13 * Отличия от модифицируемого метода * @see \Magento\Framework\Data\Form\Element\AbstractElement::getLabelHtml(): * 1) Добавляем свои классы для Font Awesome. * 2) При использовании Font Awesome не добавляем исходную подпись * (значением которой является класс Font Awesome) * и выводим, по сути, пустые теги <label><span></span></label>. * 3) Добавляем атрибут title. * 2015-12-28 * 4) Добавляем класс, соответствующий типу элемента. * * Пример использования Font Awesome: https://github.com/mage2pro/core/tree/7cb37ab2c4d728bc20d29ca3c7c643e551f6eb0a/Framework/Data/Form/Element/Font.php#L40 * * @see \Df\Framework\Form\Element\Font::onFormInitialized() * @see \Magento\Framework\Data\Form\Element\AbstractElement::getLabelHtml() * @param Sb|E $sb * @param \Closure $proceed * @param string|null $idSuffix * @return string */ public function aroundGetLabelHtml(Sb $sb, \Closure $proceed, $idSuffix = '') { /** @var string|null|Phrase $label */ $label = $sb->getLabel(); /** @var string $result */ if (is_null($label)) { $result = ''; } else { $label = (string) $label; /** * 2015-12-25 * @see \Magento\Framework\Data\Form\Element\Multiline::getLabelHtml() * имеет другое значение по-умолчанию параметра $idSuffix: * public function getLabelHtml($suffix = 0) * https://github.com/magento/magento2/blob/2.0.0/lib/internal/Magento/Framework/Data/Form/Element/Multiline.php#L59 */ if ('' === $idSuffix && $sb instanceof Multiline) { $idSuffix = 0; } /** @var bool $isFontAwesome */ $isFontAwesome = df_starts_with($label, 'fa-'); /** @var string[] $classA */ $classA = ['label', 'admin__field-label', 'df-element-' . $sb->getType()]; if ($isFontAwesome) { $classA[] = 'fa'; $classA[] = $label; $label = ''; } /** @var array(string => string) $params */ $params = ['class' => df_cc_s($classA), 'for' => $sb->getHtmlId() . $idSuffix, 'data-ui-id' => E::uidSt($sb, 'label')]; /** @var string $title */ $title = (string) $sb->getTitle(); if ($title !== $label) { $params['title'] = $title; } $result = df_tag('label', $params, df_tag('span', [], $label)) . "\n"; } return $result; }
/** * @param $number * @param string $gender * @return string */ private static function getNum1E9($number, $gender) { /** @var array(int => string) $words */ static $words = ['миллион', 'миллиона', 'миллионов']; return $number < 1000000.0 ? self::getNum1E6($number, $gender) : df_cc_s(self::getNum1000((int) ($number / 1000000.0), self::GENDER__FEMALE), dfa($words, self::getNum125((int) ($number / 1000000.0))), self::getNum1E6($number % 1000000.0, $gender)); }
/** * 2016-07-30 * Синтаксис вызова таков: self::fdCssClass($data, 'df-fe-money'); * В настоящее время нигде не используется. * @param array(string => mixed) $data * @param string $class * @return void */ private static function fdCssClass(&$data, $class) { $data[self::$FD__CSS_CLASS] = df_cc_s(dfa($data, self::$FD__CSS_CLASS), $class); }
/** * 2016-11-26 * @used-by loggedOut() * @see \Df\Sso\Button\Js::attributes() * @see \Dfe\FacebookLogin\Button::attributes() * @return array(string => string) */ protected function attributes() { return ($this->isNative() ? $this->attributesN() : ['href' => $this->lHref(), 'title' => $this->s()->label()]) + ['class' => df_cc_s('df-sso-button', $this->cssClass(), $this->s()->type(), $this->cssClass2()), 'id' => df_uid(4, "{$this->cssClass()}-"), 'rel' => 'nofollow']; }
/** * 2015-11-22 * @used-by \Df\Backend\Block\Widget\Form\Renderer\Fieldset\Element::_render() * @return string */ private function outerCssClasses() { if (!isset($this->{__METHOD__})) { /** @var string[] $resultA */ $resultA = ['admin__field field', 'df-field', $this->e()->getCssClass(), E::getClassDfOnly($this->e()), $this->e()->getContainerClass(), 'df-type-' . $this->e()->getType(), $this->shouldLabelBeAtRight() ? 'choice' : '', $this->note() ? 'with-note' : '', !$this->e()->getLabelHtml() ? 'no-label' : '']; if ($this->e()->getRequired()) { $resultA[] = 'required'; $resultA[] = '_required'; } $this->{__METHOD__} = df_cc_s($resultA); } return $this->{__METHOD__}; }
/** * 2016-03-09 * @param O $order * * 2016-03-24 * Если товар является настраиваемым, то @uses \Magento\Sales\Model\Order::getItems() * будет содержать как настраиваемый товар, так и его простой вариант. * Простые варианты игнорируем (у них имена типа «New Very Prive-36-Almond», * а нам удобнее видеть имена простыми, как у настраиваемого товара: «New Very Prive»). * * 2016-07-04 * Добавил этот параметр для модуля AllPay, где разделителем должен быть символ #. * @param string $separator [optional] * @return string */ function df_oi_s(O $order, $separator = ', ') { return df_ccc($separator, df_oi_roots_m($order, function (OI $i) { /** @var int $qty */ $qty = $i->getQtyOrdered(); return df_cc_s($i->getName(), 1 >= $qty ? null : "({$qty})"); })); }
/** * 2016-06-25 * https://mage2.pro/t/543 */ function df_magento_version_full() { /** @var ProductMetadata|ProductMetadataInterface $v */ $v = df_magento_version_m(); return df_cc_s($v->getName(), $v->getEdition(), 'Edition', $v->getVersion()); }
/** * 2016-07-13 * @return string */ public function title() { return df_cc_s($this->escapeHtml($this->getMethod()->getTitle()), $this->isTest(sprintf("(%s)", __($this->testModeLabelLong())), null)); }
/** * 2015-12-11 * $element->getClass() может вернуть строку вида: * «df-google-font df-name-family select admin__control-select». * Оставляем в ней только наши классы: чьи имена начинаются с df-. * Системные классы мы контейнеру не присваиваем, * потому что для классов типа .admin__control-select * в ядре присутствуют правила CSS, которые считают элементы с этими классами * элементами управления, а не контейнерами, и корёжат нам вёрстку. * @param AE|Element $e * @return string */ public static function getClassDfOnly(AE $e) { return df_cc_s(array_filter(df_trim(explode(' ', $e->getClass())), function ($class) { return df_starts_with($class, 'df-'); })); }