|
|
|
<?php
|
|
|
|
/*
|
|
|
|
* Copyright © 2021 ExacTI Technology Solutions. All rights reserved.
|
|
|
|
* GPLv3 General License.
|
|
|
|
* https://exacti.com.br
|
|
|
|
* Phacil PHP Framework - https://github.com/exacti/phacil-framework
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace Phacil\Framework;
|
|
|
|
|
|
|
|
use Phacil\Framework\ReflectionClass;
|
|
|
|
use Phacil\Framework\ReflectionMethod;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The registration of all objects on this Framework.
|
|
|
|
*
|
|
|
|
* @since 0.0.1
|
|
|
|
*
|
|
|
|
* @package Phacil\Framework
|
|
|
|
*/
|
|
|
|
final class Registry {
|
|
|
|
|
|
|
|
const FACTORY_CLASS = \Phacil\Framework\Factory::class;
|
|
|
|
|
|
|
|
const FACTORY_WORD_KEY = "Factory";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* data Objects
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
private $data = array();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Instances objects
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
private $instances = [];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Original route for childs
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public $routeOrig;
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public $route;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* AutoInstances Loaded
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
static private $autoInstances = [];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* DI Preference class
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
static private $preferences = [];
|
|
|
|
|
|
|
|
static private $diCheckedRoutes = [];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Magic method to return engine instances
|
|
|
|
*
|
|
|
|
* @param string $key
|
|
|
|
* @return mixed
|
|
|
|
*/
|
|
|
|
public function __get($key) {
|
|
|
|
return $this->get($key);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $key
|
|
|
|
* @return mixed
|
|
|
|
*/
|
|
|
|
public function get($key) {
|
|
|
|
|
|
|
|
return (isset($this->instances[$key]) ? $this->instances[$key] : $this->engine->checkRegistry($key));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $key
|
|
|
|
* @param mixed $value
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function set($key, $value) {
|
|
|
|
$this->instances[$key] = $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $key
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public function has($key) {
|
|
|
|
return isset($this->instances[$key]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* UnSet
|
|
|
|
*
|
|
|
|
* Unsets registry value by key.
|
|
|
|
*
|
|
|
|
* @param string $key
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function delete(string $key) {
|
|
|
|
if (isset($this->instances[$key])) {
|
|
|
|
unset($this->instances[$key]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Try to obtain an iniciated engine instance
|
|
|
|
*
|
|
|
|
* @param string|object|null $class (optional)
|
|
|
|
* @param array $args (optional)
|
|
|
|
* @param bool $onlyCheckInstances (Optional) if true, don't create an auto-instance
|
|
|
|
*
|
|
|
|
* @return \Phacil\Framework\Registry|object|null
|
|
|
|
* @since 2.0.0
|
|
|
|
*/
|
|
|
|
static public function getInstance($class = null, $args = [], $onlyCheckInstances = false) {
|
|
|
|
if(!$class) return \Phacil\Framework\startEngineExacTI::getRegistry();
|
|
|
|
|
|
|
|
$registry = \Phacil\Framework\startEngineExacTI::getRegistry();
|
|
|
|
|
|
|
|
$return = false;
|
|
|
|
|
|
|
|
$classObj = (is_object($class)) ? get_class($class) : $class;
|
|
|
|
|
|
|
|
if (isset(self::$autoInstances[($classObj)])) return self::$autoInstances[($classObj)];
|
|
|
|
|
|
|
|
foreach ($registry->instances as $value) {
|
|
|
|
if(!is_object($value)) continue;
|
|
|
|
|
|
|
|
if(get_class($value) == $classObj) {$return = $value; break; }
|
|
|
|
}
|
|
|
|
|
|
|
|
if($return) return $return;
|
|
|
|
|
|
|
|
if($onlyCheckInstances) return $return;
|
|
|
|
|
|
|
|
if(is_string($class)) {
|
|
|
|
$classCreate = self::checkPreference($class);
|
|
|
|
return self::getInstance()->injectionClass($classCreate, $args, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_object($class)) {
|
|
|
|
return self::setAutoInstance($class);
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Force the creation of an instance of a class, even if it already exists.
|
|
|
|
*
|
|
|
|
* @param string $class Class full qualified name
|
|
|
|
* @param array $args (Optional) An array with the arguments to pass to the constructor
|
|
|
|
* @return mixed
|
|
|
|
* @throws \Phacil\Framework\Exception\ReflectionException
|
|
|
|
* @throws \Phacil\Framework\Exception
|
|
|
|
*/
|
|
|
|
public function create($class, $args = array()) {
|
|
|
|
if(is_string($class)) {
|
|
|
|
return $this->injectionClass($class, $args, true);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds DI preferences from a JSON file.
|
|
|
|
*
|
|
|
|
* This method reads a JSON file containing preferences and merges them into the existing preferences array.
|
|
|
|
*
|
|
|
|
* @param string $jsonFilePath The path to the JSON file containing preferences.
|
|
|
|
* @return void
|
|
|
|
* @throws \Phacil\Framework\Exception If there is an error reading the JSON file or if the JSON data is invalid.
|
|
|
|
*/
|
|
|
|
static public function addPreference($jsonFilePath) {
|
|
|
|
$dataArray = [];
|
|
|
|
if (file_exists($jsonFilePath) && $jsonData = file_get_contents($jsonFilePath)) {
|
|
|
|
|
|
|
|
$dataArray = json_decode($jsonData, true);
|
|
|
|
|
|
|
|
// Verifica se a conversão foi bem-sucedida
|
|
|
|
if ($dataArray === null && json_last_error() !== JSON_ERROR_NONE) {
|
|
|
|
// Se houver um erro na conversão, trata o erro
|
|
|
|
$error = new \Phacil\Framework\Exception\Error(sprintf("DI preference %s error: ", $jsonFilePath). json_last_error_msg());
|
|
|
|
$error->setSeverity(E_PARSE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* if (isset($dataArray['preferences']))
|
|
|
|
self::$preferences = array_merge(self::$preferences, $dataArray['preferences']); */
|
|
|
|
|
|
|
|
if(!empty($dataArray)){
|
|
|
|
self::$preferences = self::array_merge_recursive_distinct(self::$preferences, $dataArray);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if(count($dataArray) >= 1) {
|
|
|
|
foreach($dataArray as $key => $value) {
|
|
|
|
if($key !== "preferences")
|
|
|
|
self::$diOptions[$key] = isset(self::$diOptions[$key]) ? self::array_merge_recursive_distinct(self::$diOptions[$key], $value) : $value;
|
|
|
|
}
|
|
|
|
} */
|
|
|
|
}
|
|
|
|
|
|
|
|
private static function array_merge_recursive_distinct(array $array1, array $array2)
|
|
|
|
{
|
|
|
|
$merged = $array1;
|
|
|
|
|
|
|
|
foreach ($array2 as $key => &$value) {
|
|
|
|
if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
|
|
|
|
if (is_numeric(self::array_key_first($value))) {
|
|
|
|
// Concatenate arrays if both are numeric arrays (lists)
|
|
|
|
$merged[$key] = array_merge($merged[$key], $value);
|
|
|
|
} else {
|
|
|
|
// Recursively merge associative arrays
|
|
|
|
$merged[$key] = self::array_merge_recursive_distinct($merged[$key], $value);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$merged[$key] = $value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $merged;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static function array_key_first($arr){
|
|
|
|
if (!function_exists('array_key_first')) {
|
|
|
|
foreach ($arr as $key => $unused) {
|
|
|
|
return $key;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
} else {
|
|
|
|
return array_key_first($arr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds DI preferences from a JSON file.
|
|
|
|
*
|
|
|
|
* This method reads a JSON file containing preferences and merges them into the existing preferences array.
|
|
|
|
*
|
|
|
|
* @param string $jsonFilePath The path to the JSON file containing preferences.
|
|
|
|
* @return void
|
|
|
|
* @throws \Phacil\Framework\Exception If there is an error reading the JSON file or if the JSON data is invalid.
|
|
|
|
*/
|
|
|
|
static public function addPreferenceByRoute($route, $levels = 2) {
|
|
|
|
$routeArray = explode('/', $route);
|
|
|
|
|
|
|
|
for ($i=1; $i <= $levels; $i++) {
|
|
|
|
# code...
|
|
|
|
if($i >= count($routeArray)) break;
|
|
|
|
|
|
|
|
$routeGlue = implode("/", array_slice($routeArray, 0, $i));
|
|
|
|
self::addDIrouteChecked($routeGlue);
|
|
|
|
$directory = \Phacil\Framework\Config::DIR_APP_MODULAR() . self::case_insensitive_pattern($routeGlue) . '/etc/preferences.json';
|
|
|
|
$files = glob($directory, GLOB_MARK);
|
|
|
|
if(!empty($files)) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(isset($files[0])) {
|
|
|
|
$jsonFilePath = $files[0];
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (file_exists($jsonFilePath)) {
|
|
|
|
self::addPreference($jsonFilePath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* checks if a route has already had the DI checked
|
|
|
|
* @param string $route
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
static public function isDIrouteChecked($route){
|
|
|
|
$route = strtolower($route);
|
|
|
|
return isset(self::$diCheckedRoutes[$route]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add has check DI route
|
|
|
|
* @param string $route
|
|
|
|
* @return true
|
|
|
|
*/
|
|
|
|
static public function addDIrouteChecked($route){
|
|
|
|
$route = strtolower($route);
|
|
|
|
self::$diCheckedRoutes[$route] = true;
|
|
|
|
return self::$diCheckedRoutes[$route];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param string $for
|
|
|
|
* @param string $to
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
static public function addDIPreference($for, $to) {
|
|
|
|
self::$preferences[$for]['preference'] = $to;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if preference for a class exists
|
|
|
|
*
|
|
|
|
* @param string $for
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
static public function checkPreferenceExist($for) {
|
|
|
|
return isset(self::$preferences[$for]) ? (isset(self::$preferences[$for]['preference']) ?: is_string(self::$preferences[$for])) : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if DI preferences exists
|
|
|
|
*
|
|
|
|
* @param string $for
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public static function havePreferences($class){
|
|
|
|
return isset(self::$preferences[$class]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param string $class
|
|
|
|
* @return array|null
|
|
|
|
*/
|
|
|
|
public static function getClassPreferences($class) {
|
|
|
|
return isset(self::$preferences[$class]) ? self::$preferences[$class] : null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generate Glob case insensitive pattern
|
|
|
|
* @param string $string
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
static public function case_insensitive_pattern($string)
|
|
|
|
{
|
|
|
|
$pattern = '';
|
|
|
|
foreach (str_split($string) as $char) {
|
|
|
|
if (ctype_alpha($char)) { // se o caractere é uma letra
|
|
|
|
$pattern .= '[' . strtoupper($char) . strtolower($char) . ']'; // adiciona as duas variações de caixa
|
|
|
|
} else {
|
|
|
|
$pattern .= $char; // mantém o caractere original
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $pattern;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if a preference has been set for the specified class and returns it if found.
|
|
|
|
*
|
|
|
|
* This method checks if a preference has been set for the specified class. If a preference
|
|
|
|
* is found, it returns the class name defined as the preference; otherwise, it returns the
|
|
|
|
* original class name.
|
|
|
|
*
|
|
|
|
* @param string $class The class name to check for a preference.
|
|
|
|
* @return string The class name defined as the preference, if found; otherwise, the original class name.
|
|
|
|
*/
|
|
|
|
static public function checkPreference($class) {
|
|
|
|
if(isset(self::$preferences[$class])) {
|
|
|
|
if(is_array(self::$preferences[$class]) && isset(self::$preferences[$class]['preference'])){
|
|
|
|
return self::$preferences[$class]['preference'];
|
|
|
|
} elseif(is_array(self::$preferences[$class]) && !isset(self::$preferences[$class]['preference'])) {
|
|
|
|
return $class;
|
|
|
|
}
|
|
|
|
return self::$preferences[$class];
|
|
|
|
}
|
|
|
|
return $class;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check argument type to inject
|
|
|
|
*
|
|
|
|
* @param string $class
|
|
|
|
* @param string $argument
|
|
|
|
* @return mixed
|
|
|
|
* @throws \ReflectionException
|
|
|
|
* @throws \Exception
|
|
|
|
* @throws \Phacil\Framework\Exception
|
|
|
|
*/
|
|
|
|
protected static function checkArgumentType($class, $argument) {
|
|
|
|
if(self::havePreferences($class) && is_array(self::$preferences[$class])){
|
|
|
|
if(isset(self::$preferences[$class]['arguments']) && isset(self::$preferences[$class]['arguments'][$argument])){
|
|
|
|
//Check if is an array for determine configurations
|
|
|
|
if(!is_array(self::$preferences[$class]['arguments'][$argument]))
|
|
|
|
return self::$preferences[$class]['arguments'][$argument];
|
|
|
|
|
|
|
|
if(isset(self::$preferences[$class]['arguments'][$argument]['type']) && isset(self::$preferences[$class]['arguments'][$argument]['value'])){
|
|
|
|
return self::returnArgumentType(self::$preferences[$class]['arguments'][$argument]['type'], self::$preferences[$class]['arguments'][$argument]['value']);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset(self::$preferences[$class]['arguments'][$argument]['objects'])) {
|
|
|
|
return self::returnArgumentType('object[]', self::$preferences[$class]['arguments'][$argument]['objects']);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_array(self::$preferences[$class]['arguments'][$argument]) && count(self::$preferences[$class]['arguments'][$argument]) === 1) {
|
|
|
|
$type = key(self::$preferences[$class]['arguments'][$argument]);
|
|
|
|
|
|
|
|
// Verifica se $type é um tipo válido
|
|
|
|
$validTypes = ['string', 'int', 'integer', 'bool', 'boolean', 'float', 'double', 'array', 'object', 'objects', 'object[]', 'config'];
|
|
|
|
|
|
|
|
if (in_array($type, $validTypes, true)) {
|
|
|
|
return self::returnArgumentType($type, reset(self::$preferences[$class]['arguments'][$argument]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return self::$preferences[$class]['arguments'][$argument];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Help argument type
|
|
|
|
*
|
|
|
|
* @param string $type
|
|
|
|
* @param mixed $argumentValue
|
|
|
|
* @return mixed
|
|
|
|
* @throws \ReflectionException
|
|
|
|
* @throws \Exception
|
|
|
|
* @throws \Phacil\Framework\Exception
|
|
|
|
*/
|
|
|
|
private static function returnArgumentType($type, $argumentValue) {
|
|
|
|
switch ($type) {
|
|
|
|
case 'object':
|
|
|
|
return self::getInstance($argumentValue);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'object[]':
|
|
|
|
$object = array_map(function($value){
|
|
|
|
return self::getInstance($value);
|
|
|
|
}, $argumentValue);
|
|
|
|
return $object;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'bool':
|
|
|
|
case 'boolean':
|
|
|
|
return boolval($argumentValue);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'integer':
|
|
|
|
case 'int':
|
|
|
|
return intval($argumentValue);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'config':
|
|
|
|
/** @var \Phacil\Framework\Config */
|
|
|
|
$config = self::getInstance(\Phacil\Framework\Config::class);
|
|
|
|
return $config->get($argumentValue);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return $argumentValue;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets an auto-instantiated object to be used as a dependency.
|
|
|
|
*
|
|
|
|
* This method allows you to set an object to be automatically instantiated and used as a dependency
|
|
|
|
* when resolving other dependencies that require an instance of the specified class.
|
|
|
|
*
|
|
|
|
* @param object $class The object instance to be set as an auto-instantiated dependency.
|
|
|
|
* @param string|null (Optional) $original The original class name of the object being set.
|
|
|
|
* @return object The object instance that was set as an auto-instantiated dependency.
|
|
|
|
* @throws \Phacil\Framework\Exception If the provided parameter is not an object.
|
|
|
|
* @since 2.0.0
|
|
|
|
*/
|
|
|
|
static public function setAutoInstance($class, $original = null) {
|
|
|
|
if(!is_object($class)) throw new Exception('Object type is required!');
|
|
|
|
|
|
|
|
self::$autoInstances[$original ?: get_class($class)] = $class;
|
|
|
|
return $class;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param object $class
|
|
|
|
* @return object
|
|
|
|
* @since 2.0.0
|
|
|
|
* @throws \Phacil\Framework\Exception
|
|
|
|
*/
|
|
|
|
static public function getAutoInstance($class) {
|
|
|
|
if (!is_object($class)) throw new Exception('Object type is required!');
|
|
|
|
|
|
|
|
return isset(self::$autoInstances[get_class($class)]) ? self::$autoInstances[get_class($class)] : self::setAutoInstance($class);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Resolves and instantiates a class with optional constructor arguments and creation control.
|
|
|
|
*
|
|
|
|
* This method resolves a class by its name, instantiates it with optional constructor arguments,
|
|
|
|
* and provides control over the creation process.
|
|
|
|
*
|
|
|
|
* @param string $class The fully qualified name of the class to instantiate.
|
|
|
|
* @param array $args (Optional) Arguments for the class constructor. Default is an empty array.
|
|
|
|
* If empty, constructor arguments will be automatically detected and injected.
|
|
|
|
* @param bool $forceCreate (Optional) Whether to force creation. Default is false.
|
|
|
|
* @return mixed
|
|
|
|
* @throws \ReflectionException
|
|
|
|
* @throws \Exception
|
|
|
|
* @throws \Phacil\Framework\Exception
|
|
|
|
*/
|
|
|
|
public function injectionClass($class, $args = array(), $forceCreate = false)
|
|
|
|
{
|
|
|
|
$argsToInject = !empty($args) ? $args : false;
|
|
|
|
$originalClass = $class;
|
|
|
|
$class = self::checkPreference($class);
|
|
|
|
$originalClass = $originalClass == $class ? null : $originalClass;
|
|
|
|
|
|
|
|
if($class === get_class($this)) return $this;
|
|
|
|
|
|
|
|
if (!$forceCreate && $autoInstance = $this->getInstance($originalClass ?: $class, [], true))
|
|
|
|
return $autoInstance;
|
|
|
|
|
|
|
|
$refClass = new ReflectionClass($class);
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (!$refClass->getConstructor() && !$argsToInject) {
|
|
|
|
if ($refClass->hasMethod('getInstance') && $refClass->getMethod('getInstance')->isStatic()) {
|
|
|
|
return self::setAutoInstance($refClass->getMethod('getInstance')->invoke(null), ($originalClass ?: $class));
|
|
|
|
}
|
|
|
|
return self::setAutoInstance($refClass->newInstanceWithoutConstructor(), ($originalClass ?: $class));
|
|
|
|
}
|
|
|
|
} catch (\Exception $th) {
|
|
|
|
//throw $th; Don't make anything and retry create
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
$rMethod = new ReflectionMethod($class, "__construct");
|
|
|
|
|
|
|
|
if (!$argsToInject) {
|
|
|
|
$params = $rMethod->getParameters();
|
|
|
|
$argsToInject = [];
|
|
|
|
foreach ($params as $param) {
|
|
|
|
//$param is an instance of ReflectionParameter
|
|
|
|
try {
|
|
|
|
//Check for the predefined type
|
|
|
|
if(($typeFound = self::checkArgumentType($originalClass ?: $class, $param->getName())) !== null) {
|
|
|
|
$argsToInject[$param->getPosition()] = $typeFound;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (version_compare(phpversion(), "7.2.0", "<")) {
|
|
|
|
$declaringClass = $param->__toString();
|
|
|
|
$pattern = '/\[.*?>\s*([^$\s]+)/'; //$pattern = '/<[^>]+>\s*([^$\s]+)/';
|
|
|
|
|
|
|
|
if (preg_match($pattern, $declaringClass, $matches)) {
|
|
|
|
$classFactoryName = $matches[1];
|
|
|
|
|
|
|
|
$classAttr = self::checkPreference($classFactoryName);
|
|
|
|
|
|
|
|
if (class_exists($classAttr)) {
|
|
|
|
$argsToInject[$param->getPosition()] = $this->injectionClass($classFactoryName);
|
|
|
|
continue;
|
|
|
|
} elseif (substr($classFactoryName, -(strlen(self::FACTORY_WORD_KEY))) === self::FACTORY_WORD_KEY && substr($classFactoryName, - (strlen(self::FACTORY_WORD_KEY)+1)) != "\\".self::FACTORY_WORD_KEY) {
|
|
|
|
$factoredRefClass = substr($classFactoryName, 0, -(strlen(self::FACTORY_WORD_KEY)));
|
|
|
|
|
|
|
|
if (!class_exists($classFactoryName) && $classFactoryName != self::FACTORY_CLASS) {
|
|
|
|
$argsToInject[$param->getPosition()] = ($this->getInstance($classFactoryName, [], true)) ?: self::setAutoInstance($this->create(self::FACTORY_CLASS, [$factoredRefClass]), $classFactoryName);
|
|
|
|
class_alias(self::FACTORY_CLASS, $classFactoryName);
|
|
|
|
continue;
|
|
|
|
} elseif ($classFactoryName != self::FACTORY_CLASS){
|
|
|
|
$argsToInject[$param->getPosition()] = ($this->getInstance($classFactoryName, [], true)) ?: self::setAutoInstance($this->create(self::FACTORY_CLASS, [$factoredRefClass]), $classFactoryName);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($param->getClass()) {
|
|
|
|
$injectionClass = $param->getClass()->name;
|
|
|
|
$classAttr = self::checkPreference($injectionClass);
|
|
|
|
|
|
|
|
if (class_exists($classAttr)) {
|
|
|
|
$argsToInject[$param->getPosition()] = $this->injectionClass($injectionClass);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!$param->isOptional()) {
|
|
|
|
throw new \Phacil\Framework\Exception\ReflectionException("Error Processing Request: " . $injectionClass . " not exist");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ($param->getType()) {
|
|
|
|
$injectionClass = $param->getType()->getName();
|
|
|
|
$classAttr = self::checkPreference($injectionClass);
|
|
|
|
|
|
|
|
if (class_exists($classAttr)) {
|
|
|
|
$argsToInject[$param->getPosition()] = $this->injectionClass($injectionClass);
|
|
|
|
continue;
|
|
|
|
} elseif (substr($injectionClass, -(strlen(self::FACTORY_WORD_KEY))) === self::FACTORY_WORD_KEY && substr($injectionClass, - (strlen(self::FACTORY_WORD_KEY) + 1)) != "\\" . self::FACTORY_WORD_KEY) {
|
|
|
|
// Create a factored instance
|
|
|
|
$factoredRefClass = substr($injectionClass, 0, -(strlen(self::FACTORY_WORD_KEY)));
|
|
|
|
$argsToInject[$param->getPosition()] = ($this->getInstance($injectionClass, [], true)) ?: self::setAutoInstance($this->create(self::FACTORY_CLASS, [$factoredRefClass]), $injectionClass);
|
|
|
|
class_alias(self::FACTORY_CLASS, $injectionClass);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!$param->isOptional()) {
|
|
|
|
throw new \Phacil\Framework\Exception\ReflectionException("Error Processing Request: " . $injectionClass . " not exist");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (\ReflectionException $th) {
|
|
|
|
throw new \Phacil\Framework\Exception\ReflectionException($th->getMessage(), $th->getCode(), $th);
|
|
|
|
} catch (\Exception $th) {
|
|
|
|
throw new \Phacil\Framework\Exception($th->getMessage());
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($param->isOptional() && $param->isDefaultValueAvailable()) {
|
|
|
|
$argsToInject[] = $param->getDefaultValue();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ($param->isOptional()) {
|
|
|
|
$argsToInject[] = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (\ReflectionException $th) {
|
|
|
|
throw new \Phacil\Framework\Exception\ReflectionException($th->getMessage());
|
|
|
|
} catch (\Exception $th) {
|
|
|
|
throw new \Phacil\Framework\Exception($th->getMessage());
|
|
|
|
}
|
|
|
|
|
|
|
|
return self::setAutoInstance($refClass->newInstanceArgs($argsToInject), $originalClass);
|
|
|
|
}
|
|
|
|
}
|