1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190:
<?php
namespace MvcCore\Model;
trait MetaData {
protected static function getMetaData ($propsFlags = 0) {
static $__metaData = [];
if ($propsFlags === 0)
$propsFlags = \MvcCore\IModel::PROPS_INHERIT | \MvcCore\IModel::PROPS_PROTECTED;
list (
$cacheFlags, $accessModFlags, $inclInherit
) = static::getMetaDataFlags($propsFlags);
if (isset($__metaData[$cacheFlags]))
return $__metaData[$cacheFlags];
$classFullName = get_called_class();
$metaDataItem = static::parseMetaData(
$classFullName, $accessModFlags, $inclInherit
);
$__metaData[$cacheFlags] = $metaDataItem;
return $metaDataItem;
}
protected static function parseMetaData ($classFullName, $accessModFlags, $inclInherit) {
$metaDataItem = [];
$phpWithTypes = PHP_VERSION_ID >= 70400;
$phpWithUnionTypes = PHP_VERSION_ID >= 80000;
$props = (new \ReflectionClass($classFullName))
->getProperties($accessModFlags);
foreach ($props as $prop) {
if (
$prop->isStatic() ||
(!$inclInherit && $prop->class !== $classFullName) ||
isset(static::$protectedProperties[$prop->name])
) continue;
$metaDataItem[$prop->name] = static::parseMetaDataProperty(
$prop, $phpWithTypes, $phpWithUnionTypes
);
}
return $metaDataItem;
}
protected static function parseMetaDataProperty (\ReflectionProperty $prop, $phpWithTypes, $phpWithUnionTypes) {
$types = [];
$allowNull = FALSE;
if ($phpWithTypes && $prop->hasType()) {
$refType = $prop->getType();
if ($refType !== NULL) {
if ($phpWithUnionTypes && $refType instanceof \ReflectionUnionType) {
$refTypes = $refType->getTypes();
$strIndex = NULL;
foreach ($refTypes as $index => $refTypesItem) {
$typeName = $refTypesItem->getName();
if ($strIndex === NULL && $typeName === 'string')
$strIndex = $index;
if ($typeName !== 'null')
$types[] = $typeName;
}
if ($strIndex !== NULL) {
unset($types[$strIndex]);
$types = array_values($types);
$types[] = 'string';
}
} else {
$types = [$refType->getName()];
}
$allowNull = $refType->allowsNull();
}
} else {
preg_match('/@var\s+([^\s]+)/', $prop->getDocComment(), $matches);
if ($matches) {
$rawTypes = '|'.$matches[1].'|';
$nullPos = mb_stripos($rawTypes,'|null|');
$qmPos = mb_strpos($rawTypes, '?');
$qmMatched = $qmPos !== FALSE;
$nullMatched = $nullPos !== FALSE;
$allowNull = $qmMatched || $nullMatched;
if ($qmMatched)
$rawTypes = str_replace('?', '', $rawTypes);
if ($nullMatched)
$rawTypes = (
mb_substr($rawTypes, 0, $nullPos) .
mb_substr($rawTypes, $nullPos + 5)
);
$rawTypes = mb_substr($rawTypes, 1, mb_strlen($rawTypes) - 2);
$types = explode('|', $rawTypes);
}
}
return [
$prop->isPrivate(),
$allowNull,
$types,
];
}
protected static function getMetaDataFlags ($propsFlags) {
$cacheFlags = 0;
$accessModFlags = 0;
$inclInherit = FALSE;
if (($propsFlags & \MvcCore\IModel::PROPS_INHERIT) != 0) {
$cacheFlags |= \MvcCore\IModel::PROPS_INHERIT;
$inclInherit = TRUE;
}
if (($propsFlags & \MvcCore\IModel::PROPS_PRIVATE) != 0) {
$cacheFlags |= \MvcCore\IModel::PROPS_PRIVATE;
$accessModFlags |= \ReflectionProperty::IS_PRIVATE;
}
if (($propsFlags & \MvcCore\IModel::PROPS_PROTECTED) != 0) {
$cacheFlags |= \MvcCore\IModel::PROPS_PROTECTED;
$accessModFlags |= \ReflectionProperty::IS_PROTECTED;
}
if (($propsFlags & \MvcCore\IModel::PROPS_PUBLIC) != 0) {
$cacheFlags |= \MvcCore\IModel::PROPS_PUBLIC;
$accessModFlags |= \ReflectionProperty::IS_PUBLIC;
}
return [$cacheFlags, $accessModFlags, $inclInherit];
}
}