luyadev/luya-module-admin

View on GitHub
src/models/UserSetting.php

Summary

Maintainability
A
45 mins
Test Coverage
A
98%
<?php

namespace luya\admin\models;

use yii\base\BaseObject;
use yii\db\ActiveRecordInterface;

/**
 * Store and read user settings.
 *
 * UserSettins allows you to store values a user specific inside the database. For example
 * the last state of the cms page tree.
 *
 * Store a value for a key
 *
 * ```php
 * Yii::$app->adminuser->identity->setting->set('lastPage', '.../url/to/last/page');
 * ```
 *
 * `null`, `true` and `false` are also valid values to store. To remove a settings entry call the `remove()` method:
 *
 * ```php
 * Yii::$app->adminuser->identity->setting->remove('lastPage');
 * ```
 *
 * In order to set arrayable values use dot notation, for example.
 *
 * ```php
 * Yii::$app->adminuser->identity->setting->set('menutree.id1', true);
 * Yii::$app->adminuser->identity->setting->set('menutree.id2', false);
 * ```
 *
 * The same works to get and delete array keys:
 *
 * ```php
 * Yii::$app->adminuser->identity->setting->get('menutree.id1');
 * ```
 *
 * If the key does not exists, null will be returned by default.
 *
 * @author Basil Suter <basil@nadar.io>
 * @since 1.0.0
 */
final class UserSetting extends BaseObject implements \ArrayAccess
{
    public const SEPERATOR = '.';

    public $data = [];

    public $sender;

    private function save()
    {
        if ($this->sender !== null && $this->sender instanceof ActiveRecordInterface) {
            $this->sender->updateSettings($this->data);
        }
    }

    /**
     * Get a key of the user settings, dot notation is allowed to return a key of an array.
     *
     * @param string $key
     * @param string|bool|null $default
     * @return string|array|null
     */
    public function get($key, $default = null)
    {
        $array = $this->data;
        foreach (explode(self::SEPERATOR, $key) as $item) {
            if (is_array($array) && array_key_exists($item, $array)) {
                $array = $array[$item];
            } else {
                return $default;
            }
        }

        return $array;
    }

    /**
     * Returns multiple array keys from the user settings table.
     *
     * Example usage:
     *
     * ```php
     * getArray(['key1', 'key2', [
     *     'key1' => false,
     *     'key2' => true,
     * ]);
     * ```
     *
     * The above example would return the default value true for `key2` if this element is not found inside the
     * user settings.
     *
     * @param array $keys Provide an array of keys you to select.
     * @param array $defaultMapping In order to define a default value for a given key, just use the variable name
     * as array key.`
     * @return array
     */
    public function getArray(array $keys, array $defaultMapping = [])
    {
        $data = [];
        foreach ($keys as $key) {
            $data[$key] = $this->get($key, array_key_exists($key, $defaultMapping) ? $defaultMapping[$key] : null);
        }

        return $data;
    }

    /**
     * Check if an element existing inside the user settings or not.
     *
     * @param string $key
     * @return boolean
     */
    public function has($key)
    {
        $array = $this->data;
        foreach (explode(self::SEPERATOR, $key) as $item) {
            if (is_array($array) && array_key_exists($item, $array)) {
                $array = $array[$item];
            } else {
                return false;
            }
        }

        return true;
    }

    /**
     * Remove an element from the user settings data array.
     *
     * @param string $key
     * @return bool
     */
    public function remove($key)
    {
        $lastArray = [];
        if ($this->has($key)) {
            $array = &$this->data;
            foreach (explode(self::SEPERATOR, $key) as $item) {
                if (array_key_exists($item, $array)) {
                    $lastArray = &$array;
                    $array = &$array[$item];
                }
            }

            unset($lastArray[$item]);
            if (empty($lastArray)) {
                unset($lastArray);
            }
            $this->save();
            return true;
        }

        return false;
    }

    /**
     * Add a new element to the user settings array.
     *
     * @param string $key
     * @param array|string|boolean $value
     * @return bool
     */
    public function set($key, $value)
    {
        $array = &$this->data;
        $keys = explode(self::SEPERATOR, $key);
        $i = 1;
        foreach ($keys as $item) {
            if (is_array($array) && array_key_exists($item, $array) && !is_array($array[$item]) && $i !== count($keys)) {
                return false;
            }
            $array = &$array[$item];
            $i++;
        }
        $array = $value;
        $this->save();
        return true;
    }

    // ArrayAccess

    /**
     * {@inheritDoc}
     */
    #[\ReturnTypeWillChange]
    public function offsetExists($offset)
    {
        return $this->has($offset);
    }

    /**
     * {@inheritDoc}
     */
    #[\ReturnTypeWillChange]
    public function offsetSet($offset, $value)
    {
        $this->set($offset, $value);
    }

    /**
     * {@inheritDoc}
     */
    #[\ReturnTypeWillChange]
    public function offsetUnset($offset)
    {
        $this->remove($offset);
    }

    /**
     * {@inheritDoc}
     */
    #[\ReturnTypeWillChange]
    public function offsetGet($offset)
    {
        return $this->get($offset);
    }
}