rhosocial/yii2-base-models

View on GitHub
traits/GUIDTrait.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php

/**
 *   _   __ __ _____ _____ ___  ____  _____
 *  | | / // // ___//_  _//   ||  __||_   _|
 *  | |/ // /(__  )  / / / /| || |     | |
 *  |___//_//____/  /_/ /_/ |_||_|     |_|
 * @link https://vistart.me/
 * @copyright Copyright (c) 2016 - 2023 vistart
 * @license https://vistart.me/license/
 */

namespace rhosocial\base\models\traits;

use rhosocial\base\helpers\Number;
use rhosocial\base\models\traits\config\GUIDConfig;
use yii\base\ModelEvent;

/**
 * Entity features concerning GUID.
 * @property string $GUID GUID value in 128-bit(16 bytes) binary format.
 * @property-read string $readableGUID Readable GUID value seperated with four hyphens.
 * @property-read array $guidRules
 * @version 2.0
 * @since 1.0
 * @author vistart <i@vistart.me>
 */
trait GUIDTrait
{
    
    /**
     * @var string|false REQUIRED. The attribute that will receive the GUID value.
     */
    public string|false $guidAttribute = 'guid';
    
    /**
     * DO NOT MODIFY OR OVERRIDE THIS METHOD UNLESS YOU KNOW THE CONSEQUENCES.
     * @return string
     */
    public function getReadableGuidAttribute(): string
    {
        return 'readableGuid';
    }
    
    /**
     * Attach `onInitGUIDAttribute` event.
     * @param string $eventName
     */
    protected function attachInitGUIDEvent(string $eventName): void
    {
        $this->on($eventName, [$this, 'onInitGUIDAttribute']);
    }
    
    /**
     * Initialize the GUID attribute with new generated GUID.
     * This method is ONLY used for being triggered by event. DO NOT call,
     * override or modify it directly, unless you know the consequences.
     * @param ModelEvent $event
     */
    public function onInitGUIDAttribute(mixed $event): void
    {
        $sender = $event->sender;
        /* @var $sender static */
        $sender->setGUID(static::generateGuid());
    }

    /**
     * Generate GUID in binary.
     * @return string GUID.
     */
    public static function generateGuid(): string
    {
        return Number::guid();
    }

    /**
     * Check if the $guid existed in current database table.
     * @param string $guid the GUID to be checked.
     * @return boolean Whether the $guid exists or not.
     */
    public static function checkGuidExists(string $guid): bool
    {
        return static::findOne($guid) !== null;
    }
    
    /**
     * Get the rules associated with GUID attribute.
     * @return array GUID rules.
     */
    public function getGUIDRules(): array
    {
        $rules = [];
        if (!empty($this->guidAttribute)) {
            $rules = [
                [[$this->guidAttribute], 'required',],
                [[$this->guidAttribute], 'unique',],
                [[$this->guidAttribute], 'string', 'max' => 36],
            ];
        }
        return $rules;
    }

    /**
     * Get GUID, in spite of guid attribute name.
     * @return string|null
     */
    public function getGUID(): ?string
    {
        $guidAttribute = $this->guidAttribute;
        return (!empty($guidAttribute)) ? $this->$guidAttribute : null;
    }
    
    /**
     * Get Readable GUID.
     * @return string
     */
    public function getReadableGUID(): string
    {
        $guid = $this->getGUID();
        if (preg_match(Number::GUID_REGEX, $guid)) {
            return $guid;
        }
        return Number::guid(false, false, $guid);
    }

    /**
     * Set guid, in spite of guid attribute name.
     * @param string $guid
     * @return string|null
     */
    public function setGUID(string $guid): ?string
    {
        $guidAttribute = $this->guidAttribute;
        if (empty($guidAttribute)) {
            return null;
        }
        /**
        if (preg_match(Number::GUID_REGEX, $guid)) {
            $guid = hex2bin(str_replace(['{', '}', '-'], '', $guid));
        }*/
        if (strlen($guid) == 16) {
            $guid = Number::guid(false, false, $guid);
        }
        return $this->$guidAttribute = $guid;
    }

    /**
     * Composite GUIDs from models.
     * @param mixed $models
     * @return array|string|null
     */
    public static function compositeGUIDs(mixed $models): array|string|null
    {
        if (empty($models)) {
            return null;
        }
        if (!is_array($models) && $models instanceof static) {
            return $models->getGUID();
        }
        if (is_string($models) && preg_match(Number::GUID_REGEX, $models)) {
            return $models;
        }
        $guids = [];
        foreach ($models as $model) {
            if ($model instanceof static) {
                $guids[] = $model->getGUID();
            } elseif (is_string($model)) {
                if (preg_match(Number::GUID_REGEX, $model)) {
                    $guids[] = $model;
                } elseif (strlen($model) == 16) {
                    $guids[] = Number::guid(false, false, $model);
                }
            }
        }
        return $guids;
    }

    /**
     * Composited guid string chunk into one string.
     * @param array $guids
     * @return string
     */
    public static function composite_guid_strs($guids): string
    {
        if (!is_array($guids) || empty($guids)) {
            return '';
        }
        if (is_string($guids[0]) && strlen($guids[0]) == 36) {
            return implode('', $guids);
        }
        $validGuids = Number::unsetInvalidGUIDs($guids);
        return implode('', $validGuids);
    }

    /**
     * Divide composited guid binary into chunk.
     * @param string $guids
     * @return array
     */
    public static function divide_guid_strs($guids): array
    {
        if (!is_string($guids) || strlen($guids) == 0 || strlen($guids) % 36 > 0) {
            return [];
        }
        return str_split($guids, 36);
    }

    protected function applyGUIDConfig(?GUIDConfig $guidConfig): void
    {
        if ($guidConfig == null) {
            return;
        }
        $this->guidAttribute = $guidConfig->guidAttribute;
    }
}