blog icon indicating copy to clipboard operation
blog copied to clipboard

yii2 旗标位处理公共代码

Open luckyyyyy opened this issue 7 years ago • 0 comments

<?php
/**
 * This file is part of the Muggle.
 * @copyright Copyright (c) 2017 Hangzhou Muggle Network Technology Co., Ltd.
 * @author William Chan <[email protected]>
 */
namespace app\models;

use Yii;
use yii\db\ActiveRecord;
use yii\db\Expression;

/**
 * 旗标位处理公共代码
 *
 * @author William Chan <[email protected]>
 */
trait FlagTrait
{
    /**
     * 判断属性上是否有某个旗标 (bit)
     * @param int|string $flag 旗标值或名称
     * @return bool
     */
    public function hasFlag($flag)
    {
        return $this->flag & $this->intFlagBit($flag) ? true : false;
    }

    /**
     * 判断属性上是否完全拥有某些旗标组合
     * @param int $flag 旗标组合值
     * @return bool
     */
    public function hasFullFlag($flag)
    {
        $flag = $this->intFlagBit($flag);
        return ($this->flag & $flag) === $flag ? true : false;
    }

    /**
     * 添加旗标
     * @param int|string $flag 旗标值或名称
     * @param bool $sync 是否同步写入数据库
     */
    public function addFlag($flag, $sync = false)
    {
        $flag = $this->intFlagBit($flag);
        $this->flag |= $flag;
        if ($sync && $this instanceof ActiveRecord) {
            $this->updateAll(['flag' => new Expression('flag | ' . $flag)], $this->getOldPrimaryKey(true));
        }
    }

    /**
     * 移除旗标
     * @param int|string $flag 旗标值或名称
     * @param bool $sync 是否同步写入数据库
     */
    public function removeFlag($flag, $sync = false)
    {
        $flag = $this->intFlagBit($flag);
        $this->flag &= ~$flag;
        if ($sync === true && $this instanceof ActiveRecord) {
            $this->updateAll(['flag' => new Expression('flag & ~' . $flag)], $this->getOldPrimaryKey(true));
        }
    }

    /**
     * 切换旗标
     * @param int|string $flag 旗标值或名称
     * @param bool $sync 是否同步写入数据库
     */
    public function toggleFlag($flag, $sync = false)
    {
        $flag = $this->intFlagBit($flag);
        $this->flag ^= $flag;
        if ($sync === true && $this instanceof ActiveRecord) {
            $this->updateAll(['flag' => new Expression('flag ^ ' . $flag)], $this->getOldPrimaryKey(true));
        }
    }

    /**
     * @param int|string $flag 旗标值或名称
     * @return int
     */
    private function intFlagBit($flag)
    {
        if (is_int($flag)) {
            return $flag;
        }
        $key = 'self::FLAG_' . strtoupper($flag);
        return defined($key) ? constant($key) : 0;
    }

    /**
     * 设置标记组
     * @param array $values
     */
    public function setFlags($values)
    {
        if (is_array($values)) {
            $options = static::flagOptions();
            foreach ($values as $bit => $value) {
                $bit = intval($bit);
                if (!isset($options[$bit])) {
                    continue;
                } else {
                    if ($value['have'] === true) {
                        $this->addFlag($bit);
                    } else {
                        $this->removeFlag($bit);
                    }
                }
            }
        }
    }

    /**
     * 获取标记组
     * have (bool) 代表是否设置
     * 管理员显示全部标记
     * ```json
     * {
     *     "0x1": {
     *         "have": true,
     *         "label": "超级管理员",
     *     },
     *     "0x2": {
     *         "have": false,
     *         "label": "微信管理员",
     *     }
     * }
     * ```
     * @param bool $labels 是否强制显示label 有些label不能给用户看
     * @return array
     */
    public function getFlags($labels = false)
    {
        $flags = [];
        $isSuper = Yii::$app->user->isSuper;
        foreach (static::flagOptions() as $flag => $label) {
            $have = $this->hasFlag($flag);
            if ($isSuper || $have) {
                $dat = ['have' => $have];
                if ($isSuper || $labels) {
                    $dat['label'] = $label;
                }
                $flags[$flag] = $dat;
            }
        }
        return $flags;
    }

}

luckyyyyy avatar Dec 22 '17 20:12 luckyyyyy