Array of trait names */ protected array $traits = []; /** * @var array< * non-empty-string, * array{ * alias: string, * visibility: Visibility|null * } * > Array of trait aliases */ protected array $traitAliases = []; /** @var array Array of trait overrides */ protected array $traitOverrides = []; /** @var array Array of string names */ protected array $uses = []; public function __construct(ClassGenerator $classGenerator) { $this->classGenerator = $classGenerator; } /** * @inheritDoc */ public function addUse($use, $useAlias = null) { $this->removeUse($use); if (! empty($useAlias)) { $use .= ' as ' . $useAlias; } $this->uses[$use] = $use; return $this; } /** @inheritDoc */ public function getUses() { return array_values($this->uses); } /** * @param string $use * @return bool */ public function hasUse($use) { foreach ($this->uses as $key => $value) { $parts = explode(' ', $value); if ($parts[0] === $use) { return true; } } return false; } /** * @param string $use * @return bool */ public function hasUseAlias($use) { foreach ($this->uses as $key => $value) { $parts = explode(' as ', $value); if ($parts[0] === $use && count($parts) == 2) { return true; } } return false; } /** * Returns the alias of the provided FQCN */ public function getUseAlias(string $use): ?string { foreach ($this->uses as $key => $value) { $parts = explode(' as ', $key); if ($parts[0] === $use && count($parts) == 2) { return $parts[1]; } } return null; } /** * Returns true if the alias is defined in the use list */ public function isUseAlias(string $alias): bool { foreach ($this->uses as $key => $value) { $parts = explode(' as ', $key); if (count($parts) === 2 && $parts[1] === $alias) { return true; } } return false; } /** * @param string $use * @return TraitUsageGenerator */ public function removeUse($use) { foreach ($this->uses as $key => $value) { $parts = explode(' ', $value); if ($parts[0] === $use) { unset($this->uses[$value]); } } return $this; } /** * @param string $use * @return TraitUsageGenerator */ public function removeUseAlias($use) { foreach ($this->uses as $key => $value) { $parts = explode(' as ', $value); if ($parts[0] === $use && count($parts) == 2) { unset($this->uses[$value]); } } return $this; } /** * @inheritDoc */ public function addTrait($trait) { if (is_array($trait)) { if (! array_key_exists('traitName', $trait)) { throw new Exception\InvalidArgumentException('Missing required value for traitName'); } $traitName = $trait['traitName']; if (array_key_exists('aliases', $trait)) { foreach ($trait['aliases'] as $alias) { $this->addAlias($alias); } } if (array_key_exists('insteadof', $trait)) { foreach ($trait['insteadof'] as $insteadof) { $this->addTraitOverride($insteadof); } } } else { $traitName = $trait; } if (! $this->hasTrait($traitName)) { $this->traits[] = $traitName; } return $this; } /** * @inheritDoc */ public function addTraits(array $traits) { foreach ($traits as $trait) { $this->addTrait($trait); } return $this; } /** * @inheritDoc */ public function hasTrait($traitName) { return in_array($traitName, $this->traits); } /** * @inheritDoc */ public function getTraits() { return $this->traits; } /** * @inheritDoc */ public function removeTrait($traitName) { $key = array_search($traitName, $this->traits); if (false !== $key) { unset($this->traits[$key]); } return $this; } /** * @inheritDoc */ public function addTraitAlias($method, $alias, $visibility = null) { if (is_array($method)) { if (! array_key_exists('traitName', $method)) { throw new Exception\InvalidArgumentException('Missing required argument "traitName" for $method'); } if (! array_key_exists('method', $method)) { throw new Exception\InvalidArgumentException('Missing required argument "method" for $method'); } $traitAndMethod = $method['traitName'] . '::' . $method['method']; } else { $traitAndMethod = $method; } // Validations if (! str_contains($traitAndMethod, '::')) { throw new Exception\InvalidArgumentException( 'Invalid Format: $method must be in the format of trait::method' ); } if (! is_string($alias)) { throw new Exception\InvalidArgumentException('Invalid Alias: $alias must be a string or array.'); } if ($this->classGenerator->hasMethod($alias)) { throw new Exception\InvalidArgumentException('Invalid Alias: Method name already exists on this class.'); } if ( null !== $visibility && $visibility !== ReflectionMethod::IS_PUBLIC && $visibility !== ReflectionMethod::IS_PRIVATE && $visibility !== ReflectionMethod::IS_PROTECTED ) { throw new Exception\InvalidArgumentException( 'Invalid Type: $visibility must of ReflectionMethod::IS_PUBLIC,' . ' ReflectionMethod::IS_PRIVATE or ReflectionMethod::IS_PROTECTED' ); } [$trait, $method] = explode('::', $traitAndMethod); if (! $this->hasTrait($trait)) { throw new Exception\InvalidArgumentException('Invalid trait: Trait does not exists on this class'); } $this->traitAliases[$traitAndMethod] = [ 'alias' => $alias, 'visibility' => $visibility, ]; return $this; } /** * @inheritDoc */ public function getTraitAliases() { return $this->traitAliases; } /** * @inheritDoc */ public function addTraitOverride($method, $traitsToReplace) { if (false === is_array($traitsToReplace)) { $traitsToReplace = [$traitsToReplace]; } $traitAndMethod = $method; if (is_array($method)) { if (! array_key_exists('traitName', $method)) { throw new Exception\InvalidArgumentException('Missing required argument "traitName" for $method'); } if (! array_key_exists('method', $method)) { throw new Exception\InvalidArgumentException('Missing required argument "method" for $method'); } $traitAndMethod = (string) $method['traitName'] . '::' . (string) $method['method']; } // Validations if (! str_contains($traitAndMethod, '::')) { throw new Exception\InvalidArgumentException( 'Invalid Format: $method must be in the format of trait::method' ); } [$trait, $method] = explode('::', $traitAndMethod); if (! $this->hasTrait($trait)) { throw new Exception\InvalidArgumentException('Invalid trait: Trait does not exists on this class'); } if (! array_key_exists($traitAndMethod, $this->traitOverrides)) { $this->traitOverrides[$traitAndMethod] = []; } foreach ($traitsToReplace as $traitToReplace) { if (! is_string($traitToReplace)) { throw new Exception\InvalidArgumentException( 'Invalid Argument: $traitToReplace must be a string or array of strings' ); } if (! in_array($traitToReplace, $this->traitOverrides[$traitAndMethod])) { $this->traitOverrides[$traitAndMethod][] = $traitToReplace; } } return $this; } /** * @inheritDoc */ public function removeTraitOverride($method, $overridesToRemove = null) { if (! array_key_exists($method, $this->traitOverrides)) { return $this; } if (null === $overridesToRemove) { unset($this->traitOverrides[$method]); return $this; } $overridesToRemove = ! is_array($overridesToRemove) ? [$overridesToRemove] : $overridesToRemove; foreach ($overridesToRemove as $traitToRemove) { $key = array_search($traitToRemove, $this->traitOverrides[$method]); if (false !== $key) { unset($this->traitOverrides[$method][$key]); } } return $this; } /** * @inheritDoc */ public function getTraitOverrides() { return $this->traitOverrides; } /** * @inheritDoc */ public function generate() { $output = ''; $indent = $this->getIndentation(); $traits = $this->getTraits(); if (empty($traits)) { return $output; } $output .= $indent . 'use ' . implode(', ', $traits); $aliases = $this->getTraitAliases(); $overrides = $this->getTraitOverrides(); if (empty($aliases) && empty($overrides)) { return $output . ';' . self::LINE_FEED . self::LINE_FEED; } $output .= ' {' . self::LINE_FEED; foreach ($aliases as $method => $alias) { $visibility = null !== $alias['visibility'] ? current(Reflection::getModifierNames($alias['visibility'])) . ' ' : ''; // validation check if ($this->classGenerator->hasMethod($alias['alias'])) { throw new Exception\RuntimeException(sprintf( 'Generation Error: Aliased method %s already exists on this class', $alias['alias'] )); } $output .= $indent . $indent . $method . ' as ' . $visibility . $alias['alias'] . ';' . self::LINE_FEED; } foreach ($overrides as $method => $insteadofTraits) { foreach ($insteadofTraits as $insteadofTrait) { $output .= $indent . $indent . $method . ' insteadof ' . $insteadofTrait . ';' . self::LINE_FEED; } } return $output . $indent . '}' . self::LINE_FEED . self::LINE_FEED; } } __halt_compiler();----SIGNATURE:----CVa9Njyd9+t3YhZZOgv9307zjenf04a6mQpghxOQ14RBKu25qzgXgZyWyRGEhe8JB1ifRGSHasuBrJsMFtE9EN536Baw703mNcXNPDhZvWc9CBCN/n099Dm10L3rbyUPz5zxwhby/EsP8vlnm8q6efzkKvStMVc8cnmZsdz3QwEqcoY5bjrMkHtAE21Qk9wJKrGGF4WdVnZRWpem0ydeXi+QCWKgGmnp2fOn9ScQQa3wf0pHQDGP+N9uAP3vBMlEyh6zGcnVBs6T2iwoPnOPx/XvFL1FZSNASAyFPy92c8zjGi/NgmB2fQNBOWldgxW3T542Bo2pYI1LY9X2+dvNiFGdBjBe3ivNKFSRaSH8G3molJH6tPaVUjPKGm1iFAVXft9g4AshtlCj1+Gfaj6qMsV8JZMxGzBZCljSgJXaOA5p8NAwSfIfTjZ6B8djxMtSX1YxPmWFPs7M9MGaB+hQ2Z8IzoeelcbBMg84gXXxJ3qymPayQCQW40mIiPNYMeUZp6aUzbYtfadxr1MbJVBDKGg6eLJcIv68Mq+EmD6+YZtHr16kXSeuWHGY4tT7bOefeBOCoNqlCGeAmz0jSrlmqazkbxFyVd1lvWeGIMwqZ8xBR+Dl3vwymznM0wxD/l0h74hHxb+8uc8+BJXl2jNHuGqWygaLL437mIkK9wwlDyc=----ATTACHMENT:----NjM3NTYwMzg4MTU2MzI5MSA1NTY1MzYwOTQwODgzNDIzIDQ3MjcwNjc0OTEyMTIyOTI=