Passed
Push — master ( 8c763d...c38a81 )
by Akpé Aurelle Emmanuel Moïse
35s
created

Shortcut::useTheRightName()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 2
nop 4
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
namespace EZAMA
3
4
/**
5
*
6
* @Name : Shortcut
7
* @Version : 1.0.0
8
* @Programmer : Akpé Aurelle Emmanuel Moïse Zinsou
9
* @Date : 2019-04-01
10
* @Released under : https://github.com/manuwhat/Shortcut/blob/master/LICENSE
11
* @Repository : https://github.com/manuwhat/Shortcut
12
*
13
**/
14
{
15
16
    class Shortcut
17
    {
18
        const VALID_PHP_FUNCTION_NAME_PATTERN = '#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$#';
19
        const CAN_NEVER_EVER_CHOOSE_THIS_AS_FUNCTION_NAME= "new";
20
        const PLACEHOLDER_FOR_INTERNALS_CLASSES_OPTIONALS_PARAMETERS ="This is internal and thus sucks we must do something ClassShortcutDesigner";
21
        private static $DIR=null;
22
        
23
        public static function create($classname, $name=self::CAN_NEVER_EVER_CHOOSE_THIS_AS_FUNCTION_NAME)
24
        {
25
            if (is_string($classname)&&class_exists($classname, true)) {
26
                $reflectionClass=new \reflectionClass($classname);
27
                $classname=$reflectionClass->getName();
28
                $fullQualifiedClassname=str_replace('\\', '_', $classname);
29
                if ($Dir=self::$DIR) {
30
                    $file=self::$DIR.DIRECTORY_SEPARATOR.$fullQualifiedClassname.".Shortcut.php";
31
                } else {
32
                    $Dir=dirname(__DIR__).DIRECTORY_SEPARATOR.'ClassShortcuts';
33
                    $file=$Dir.DIRECTORY_SEPARATOR.$fullQualifiedClassname.".Shortcut.php";
34
                }
35
                $fileExists=file_exists($file);
36
                if (!function_exists($classname)&&!function_exists($name)) {
37
                    if (!$fileExists) {
38
                        $name=trim($name);
39
                        if (!file_exists($Dir)) {
40
                            mkdir($Dir);
41
                        }
42
                        $reflectionMethod=$reflectionClass->getConstructor();
43
                        $notInstantiable=false;
44
                        if (is_null($reflectionMethod)||$notInstantiable=!$reflectionClass->isInstantiable()) {
45
                            if ($notInstantiable) {
46
                                throw new \InvalidArgumentException('Not Instantiable class '.$fullQualifiedClassname.' passed as Argument');
47
                            } else {
48
                                self::useTheRightName($Shortcut, $name, $fullQualifiedClassname, '');
49
                                
50
                                $Shortcut.="return new $classname();
51
                                        }";
52
                                return self::pushAndShow($file, $Shortcut);
53
                            }
54
                        }
55
                        self::getSignature($reflectionMethod, $signature, $parameters, $paramsNum, $count);
56
                        
57
                        $hasInternal='';
58
                        if ($count) {
59
                            self::BuildTheSwitch($hasInternal, $count, $paramsNum, $parameters, $classname);
60
                        }
61
                        self::useTheRightName($Shortcut, $name, $fullQualifiedClassname, $signature);
62
                        
63
                        self::handleInternals($Shortcut, $hasInternal, $parameters, $signature, $classname);
64
                            
65
                        return self::pushAndShow($file, $Shortcut);
66
                    } else {
67
                        return include_once($file);
68
                    }
69
                } else {
70
                    if (!$fileExists) {
71
                        if (strtolower($name)!=='new'&&preg_match(self::VALID_PHP_FUNCTION_NAME_PATTERN, $name)) {
72
                            throw new \InvalidArgumentException('function '.$name.' passed as second Argument already exists.
73
							Can\'t create a shortcut with the same name');
74
                        } else {
75
                            throw new \InvalidArgumentException('function '.$fullQualifiedClassname.' already exists and An alias has not been provided as Argument 2.
76
							Can\'t create a shortcut function with this name');
77
                        }
78
                    }
79
                }
80
            }
81
        }
82
83
        private static function getSignature(\ReflectionMethod $method, &$signature, &$parameters, &$paramsNum, &$count)
84
        {
85
            $params=$method->getParameters();
86
            $paramsNum=count($params);
87
            $signature='';
88
            $parameters=array();
89
            $count=0;
90
            foreach ($params as $k=>$param) {
91
                if ($param->isPassedByReference()) {
92
                    $tmp='&$'.$param->getName();
93
                } else {
94
                    $tmp='$'.$param->getName();
95
                }
96
97
                if ($param->isOptional()) {
98
                    $count++;
99
                    if ($method->isInternal()) {
100
                        $tmp.='="This is internal and thus sucks we must do something ClassShortcutDesigner"';
101
                    } elseif ($param->isDefaultValueConstant()) {
102
                        $tmp.='='.$param->getDefaultValueConstantName;
0 ignored issues
show
Bug introduced by
The property getDefaultValueConstantName does not seem to exist on ReflectionParameter.
Loading history...
103
                    } elseif ($param->isDefaultValueAvailable()) {
104
                        $tmp.='='.var_export($param->getDefaultValue(), true);
105
                    } elseif ($param->allowsNull()) {
106
                        $tmp.='=null';
107
                    }
108
                }
109
                
110
                $signature.=$tmp;
111
                $parameters[]='$'.$param->getName();
112
                $tmp='';
113
                if ($k<$paramsNum-1) {
114
                    $signature.=',';
115
                }
116
            }
117
        }
118
        private static function BuildTheSwitch(&$hasInternal, $count, $paramsNum, $parameters, $classname)
119
        {
120
            $hasInternal.='switch($count){';
121
            while ($count>0) {
122
                $hasInternal.="case $count:return new $classname(".join(',', array_slice($parameters, 0, $paramsNum-$count))."); break;";
123
                $count--;
124
            }
125
            $hasInternal.='default:return new '. $classname.'('.join(',', $parameters).');break;}';
126
        }
127
        
128
        private static function useTheRightName(&$Shortcut, $name, $fullQualifiedClassname, $signature)
129
        {
130
            if (strtolower($name)!=='new'&&preg_match(self::VALID_PHP_FUNCTION_NAME_PATTERN, $name)) {
131
                $Shortcut="<?php
132
							function $name($signature){";
133
            } else {
134
                $Shortcut="<?php
135
							function $fullQualifiedClassname($signature){";
136
            }
137
        }
138
        
139
        private static function handleInternals(&$Shortcut, $hasInternal, $parameters, $signature, $classname)
140
        {
141
            if (!strpos($signature, "This is internal and thus sucks we must do something ClassShortcutDesigner")) {
142
                $Shortcut.="return new $classname(".join(',', $parameters).");
143
							}";
144
            } else {
145
                $Shortcut.='
146
							$count=count(array_keys(get_defined_vars(),"'.self::PLACEHOLDER_FOR_INTERNALS_CLASSES_OPTIONALS_PARAMETERS.'"));
147
							'.$hasInternal.'
148
							}';
149
            }
150
        }
151
        
152
        private static function pushAndShow($file, $Shortcut)
153
        {
154
            file_put_contents($file, str_replace("\t", '    ', $Shortcut));
155
            file_put_contents($file, php_strip_whitespace($file));//just for cleanliness of the generated code
156
            return include_once($file);
157
        }
158
        
159
        public static function setDir($dirname)
160
        {
161
            if (is_dir($dirname)&&is_writable($dirname)&&!self::$DIR) {
162
                self::$DIR=$dirname;
163
            }
164
        }
165
        
166
        private function __construct()
167
        {
168
        }
169
    }
170
}
171
172
namespace{
173
    function create_Shortcut($classname, $name='new')
174
    {
175
        return EZAMA\Shortcut::create($classname, $name);
176
    }
177
}
178