Completed
Branch master (744470)
by Akpé Aurelle Emmanuel Moïse
01:48
created

Shortcut::createDir()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 4
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
                self::getTheRightDir($file, $Dir, $fullQualifiedClassname);
30
                $fileExists=file_exists($file);
31
                if (!function_exists($classname)&&!function_exists($name)) {
32
                    if (!$fileExists) {
33
                        $name=trim($name);
34
                        self::createDir($Dir);
35
                        $reflectionMethod=$reflectionClass->getConstructor();
36
                        $notInstantiable=false;
37
                        if (is_null($reflectionMethod)||$notInstantiable=!$reflectionClass->isInstantiable()) {
38
                            return self::HandleNotInstantiableAndHasNoConstructor($Shortcut, $fullQualifiedClassname, $name, $notInstantiable, $file, $classname);
39
                        }
40
                        self::getSignature($reflectionMethod, $signature, $parameters, $paramsNum, $count);
41
                        
42
                        $hasInternal='';
43
                        if ($count) {
44
                            self::BuildTheSwitch($hasInternal, $count, $paramsNum, $parameters, $classname);
45
                        }
46
                        self::useTheRightName($Shortcut, $name, $fullQualifiedClassname, $signature);
47
                        
48
                        self::handleInternals($Shortcut, $hasInternal, $parameters, $signature, $classname);
49
                            
50
                        return self::pushAndShow($file, $Shortcut);
51
                    } else {
52
                        return include_once($file);
53
                    }
54
                } else {
55
                    self::GetTheRightExceptionMessage($fileExists, $name, $fullQualifiedClassname);
56
                }
57
            }
58
        }
59
60
        private static function getSignature(\ReflectionMethod $method, &$signature, &$parameters, &$paramsNum, &$count)
61
        {
62
            $params=$method->getParameters();
63
            $paramsNum=count($params);
64
            $signature='';
65
            $parameters=array();
66
            $count=0;
67
            foreach ($params as $k=>$param) {
68
                if ($param->isPassedByReference()) {
69
                    $tmp='&$'.$param->getName();
70
                } else {
71
                    $tmp='$'.$param->getName();
72
                }
73
74
                if ($param->isOptional()) {
75
                    $count++;
76
                    if ($method->isInternal()) {
77
                        $tmp.='="This is internal and thus sucks we must do something ClassShortcutDesigner"';
78
                    } elseif ($param->isDefaultValueConstant()) {
79
                        $tmp.='='.$param->getDefaultValueConstantName();
80
                    } elseif ($param->isDefaultValueAvailable()) {
81
                        $tmp.='='.var_export($param->getDefaultValue(), true);
82
                    } elseif ($param->allowsNull()) {
83
                        $tmp.='=null';
84
                    }
85
                }
86
                
87
                $signature.=$tmp;
88
                $parameters[]='$'.$param->getName();
89
                $tmp='';
90
                if ($k<$paramsNum-1) {
91
                    $signature.=',';
92
                }
93
            }
94
        }
95
        private static function BuildTheSwitch(&$hasInternal, $count, $paramsNum, $parameters, $classname)
96
        {
97
            $hasInternal.='switch($count){';
98
            while ($count>0) {
99
                $hasInternal.="case $count:return new $classname(".join(',', array_slice($parameters, 0, $paramsNum-$count))."); break;";
100
                $count--;
101
            }
102
            $hasInternal.='default:return new '. $classname.'('.join(',', $parameters).');break;}';
103
        }
104
        
105
        private static function useTheRightName(&$Shortcut, $name, $fullQualifiedClassname, $signature)
106
        {
107
            if (strtolower($name)!=='new'&&preg_match(self::VALID_PHP_FUNCTION_NAME_PATTERN, $name)) {
108
                $Shortcut="<?php
109
							function $name($signature){";
110
            } else {
111
                $Shortcut="<?php
112
							function $fullQualifiedClassname($signature){";
113
            }
114
        }
115
        
116
        private static function handleInternals(&$Shortcut, $hasInternal, $parameters, $signature, $classname)
117
        {
118
            if (!strpos($signature, "This is internal and thus sucks we must do something ClassShortcutDesigner")) {
119
                $Shortcut.="return new $classname(".join(',', $parameters).");
120
							}";
121
            } else {
122
                $Shortcut.='
123
							$count=count(array_keys(get_defined_vars(),"'.self::PLACEHOLDER_FOR_INTERNALS_CLASSES_OPTIONALS_PARAMETERS.'"));
124
							'.$hasInternal.'
125
							}';
126
            }
127
        }
128
        
129
        private static function pushAndShow($file, $Shortcut)
130
        {
131
            file_put_contents($file, str_replace("\t", '    ', $Shortcut));
132
            file_put_contents($file, php_strip_whitespace($file));//just for cleanliness of the generated code
133
            return include_once($file);
134
        }
135
        
136
        private static function GetTheRightExceptionMessage($fileExists, $name, $fullQualifiedClassname)
137
        {
138
            if (!$fileExists) {
139
                if (strtolower($name)!=='new'&&preg_match(self::VALID_PHP_FUNCTION_NAME_PATTERN, $name)) {
140
                    throw new \InvalidArgumentException('function '.$name.' passed as second Argument already exists.
141
					Can\'t create a shortcut with the same name');
142
                } else {
143
                    throw new \InvalidArgumentException('function '.$fullQualifiedClassname.' already exists and An alias has not been provided as Argument 2.
144
					Can\'t create a shortcut function with this name');
145
                }
146
            }
147
        }
148
        
149
        private static function HandleNotInstantiableAndHasNoConstructor(&$Shortcut, $fullQualifiedClassname, $name, $notInstantiable, $file, $classname)
150
        {
151
            if ($notInstantiable) {
152
                throw new \InvalidArgumentException('Not Instantiable class '.$fullQualifiedClassname.' passed as Argument');
153
            } else {
154
                self::useTheRightName($Shortcut, $name, $fullQualifiedClassname, '');
155
                
156
                $Shortcut.="return new $classname();
157
						}";
158
                return self::pushAndShow($file, $Shortcut);
159
            }
160
        }
161
        
162
        private static function getTheRightDir(&$file, &$Dir, $fullQualifiedClassname)
163
        {
164
            if ($Dir=self::$DIR) {
165
                $file=self::$DIR.DIRECTORY_SEPARATOR.$fullQualifiedClassname.".Shortcut.php";
166
            } else {
167
                $Dir=dirname(__DIR__).DIRECTORY_SEPARATOR.'ClassShortcuts';
168
                $file=$Dir.DIRECTORY_SEPARATOR.$fullQualifiedClassname.".Shortcut.php";
169
            }
170
        }
171
        
172
        private static function createDir($Dir)
173
        {
174
            if (!file_exists($Dir)) {
175
                mkdir($Dir);
176
            }
177
        }
178
        
179
        
180
        
181
        public static function setDir($dirname)
182
        {
183
            if (is_dir($dirname)&&is_writable($dirname)&&!self::$DIR) {
184
                self::$DIR=$dirname;
185
            }
186
        }
187
        
188
        
189
        private function __construct()
190
        {
191
        }
192
    }
193
}
194
195
namespace{
196
    function create_Shortcut($classname, $name='new')
197
    {
198
        return EZAMA\Shortcut::create($classname, $name);
199
    }
200
}
201