YiiRocks/yii2-fontawesome-inline

View on GitHub
src/bootstrap4/ActiveField.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

namespace thoulah\fontawesome\bootstrap4;

use thoulah\fontawesome\config\Options;
use thoulah\fontawesome\Icon;
use thoulah\fontawesome\IconComponent;
use Yii;
use yii\helpers\ArrayHelper;

/**
 * Provides an easy way to use icons in forms are described on the Boostrap
 * [Input group](https://getbootstrap.com/docs/4.3/components/input-group/) page.
 *
 * ## Automatic
 *
 * ```php
 * use thoulah\fontawesome\bootstrap4\ActiveForm;
 *
 * $form = ActiveForm::begin();
 *
 * echo $form->field($model, 'field1', [
 *     'icon' => 'user',
 * ]);
 *
 * echo $form->field($model, 'field2', [
 *     'icon' => [
 *         'name' => 'github',
 *         'style' => 'brands',
 *     ],
 * ]);
 *
 * echo $form->field($model, 'field3', [
 *     'icon' => [
 *         'name' => 'github',
 *         'style' => 'brands',
 *         'append' => true,
 *     ],
 * ]);
 *
 * ActiveForm::end();
 * ```
 *
 * ## Manual
 *
 * For `$icon` you can use [[Icon]] or [[IconComponent]].
 *
 * ```php
 * $form = ActiveForm::begin();
 *
 * echo $form->field($model, 'field', [
 *     'inputTemplate' => $icon->activeFieldAddon('user'),
 * ]);
 *
 * ActiveForm::end();
 * ```
 *
 * ```php
 * $form = ActiveForm::begin();
 *
 * echo $form->field($model, 'field', [
 *     'inputTemplate' => '<div id="yourClass" class="float-right">YourText</div>' .
 *         $icon->activeFieldAddon('font-awesome', ['style' => 'brands']),
 * ]);
 *
 * ActiveForm::end();
 * ```
 *
 * ```php
 * $form = ActiveForm::begin();
 *
 * echo $form->field($model, 'field', [
 *     'inputTemplate' => '<div class="input-group">YourText' .
 *         $icon->activeFieldIcon('font-awesome', ['style' => 'brands']).'{input}</div>',
 * ]);
 *
 * ActiveForm::end();
 * ```
 */
class ActiveField extends \yii\bootstrap4\ActiveField
{
    /** @var array per-icon settings */
    public $icon;

    /**
     * Constructor.
     *
     * @param array $config name-value pairs that will be used to initialize the object properties
     */
    public function __construct($config = [])
    {
        $icon = ArrayHelper::getValue($config, 'icon');
        if (is_string($icon)) {
            ArrayHelper::setValue($config, 'icon', ['name' => $icon]);
        }

        parent::__construct($config);
    }

    /**
     * Renders the whole field.
     *
     * @param string|callable $content the content within the field container
     *
     * @return string the rendering result
     */
    public function render($content = null): string
    {
        if (!empty($this->icon)) {
            $groupSize = ArrayHelper::remove($this->icon, 'groupSize');
            $append = ArrayHelper::getValue($this->icon, 'append');

            $fieldAddon = Html::activeFieldAddon($groupSize, $append);
            $fieldIcon = Html::activeFieldIcon($append);
            $inputTemplate = str_replace('{icon}', $fieldIcon, $fieldAddon);
            $this->inputTemplate = str_replace('{icon}', $this->callComponentOrClass(), $inputTemplate);
        }

        return parent::render($content);
    }

    /**
     * Tries to find component id. If that cannot be found we fall be to running as class.
     *
     * @return string The icon
     */
    private function callComponentOrClass(): string
    {
        foreach (Yii::$app->components as $key => $value) {
            if (is_object($value['class']) && in_array(IconComponent::class, [$value['class'], get_parent_class($value['class'])])) {
                return $this->runAsComponent(Yii::$app->$key);
            }
        }

        return $this->runAsClass();
    }

    /**
     * We run as class.
     *
     * @return string The icon
     */
    private function runAsClass(): string
    {
        $icon = new Icon();
        $iconName = ArrayHelper::remove($this->icon, 'name');

        if (!isset($this->icon['fixedWidth'])) {
            $this->icon['fixedWidth'] = $icon->defaults->activeFormFixedWidth;
        }

        return $icon->show($iconName ?? '', $this->icon);
    }

    /**
     * We run as component.
     *
     * @param IconComponent $icon
     *
     * @return string The icon
     */
    private function runAsComponent(IconComponent $icon): string
    {
        $iconName = ArrayHelper::remove($this->icon, 'name');
        $iconStyle = ArrayHelper::remove($this->icon, 'style');
        $icon->name($iconName ?? '', $iconStyle);

        $fixedWidth = ArrayHelper::remove($this->icon, 'fixedWidth', $icon->defaults->activeFormFixedWidth);
        $icon->fixedWidth($fixedWidth);

        $properties = get_object_vars(new Options());
        foreach (array_keys($properties) as $property) {
            $value = ArrayHelper::remove($this->icon, $property);
            if (null !== $value) {
                $icon->$property($value);
            }
        }

        return $icon;
    }
}