A PHP-ben az objektumtulajdonságok beállítására van egy beépített lehetőség (__get() és __set() metódusok), azonban ezek nem típusbiztosak, így ajánlott saját getter és setter metódusokat írni a tulajdonságok kezelésére. Viszont ez igen időigényes feladat, és a Zend Studio-n kívül még nem találkoztam IDE-vel, ami megtenné helyettem, úgyhogy írtam egy kódot ennek a folyamatnak az automatizálására.
Ez a leírás elsősorben Windows felhasználóknak lesz hasznos, viszont a kódolás gyorsítására érdemes lehet kipróbálni a scriptet más rendszer alatt fejlesztőknek is.
Hogy teljesen világos legyen mindenki számára, hogy mit értek getter és setter metódusok alatt, íme egy példa:
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 | <?php namespace valami\tartalom\menedzser; /** * Egy tartalomkezelőben egy leírást reprezentáló osztály * @author BlackY */ class Content { /** * A leírás címe * @var string */ private $title; /** * A leírás beküldője * @var \valami\tartalom\menedzser\felhasznaloKezeles\Felhasznalo */ private $author; /** * A leírás szövege * @var string */ private $text; /** * A leíráshoz kapcsolt tagok * @var array */ private $tags; } |
Az adattagokat az adatelrejtés okán priváttá tettük, viszont valahogy el kéne érni őket. Első próbálkozás lehet a __get() és __set() metódusok használata, azonban az nem típusbíztos: ha biztonságos kódot szeretnénk írni, mindig tesztelnünk kéne az author tulajdonság értékét, hogy null-e ill. objektum-e ill. a megfelelő osztály egy példánya-e.
Azonban ha biztosra tudjuk, hogy az author \valami\tartalom\menedzser\felhasznaloKezeles\Felhasznalo objektum (a sok \ az ún. névteret adja meg) akkor a plusz ellenőrzések feleslegessé válnak.
Ugyanez az osztály az összes getter/setter metódussal:
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 | <?php namespace valami\tartalom\menedzser; class Content { /** * A leírás címe * @var string */ private $title; /** * A leírás beküldője * @var \valami\tartalom\menedzser\felhasznaloKezeles\Felhasznalo */ private $author; /** * A leírás szövege * @var string */ private $text; /** * A leíráshoz kapcsolt tagok * @var array */ private $tags; /** * Getter method of the title property * @return string */ public function getTitle() { return $this->title; } /** * Setter method of the title property * @param string $value - The new value of the property * @return valami\tartalom\menedzser\Content */ public function setTitle($title) { $this->title = (string)$title; return $this; } /** * Getter method of the author property * @return \valami\tartalom\menedzser\felhasznaloKezeles\Felhasznalo */ public function getAuthor() { return $this->author; } /** * Setter method of the author property * @param \valami\tartalom\menedzser\felhasznaloKezeles\Felhasznalo $value - The new value of the property * @return valami\tartalom\menedzser\Content */ public function setAuthor(\valami\tartalom\menedzser\felhasznaloKezeles\Felhasznalo $author) { $this->author = $author; return $this; } /** * Getter method of the text property * @return string */ public function getText() { return $this->text; } /** * Setter method of the text property * @param string $value - The new value of the property * @return valami\tartalom\menedzser\Content */ public function setText($text) { $this->text = (string)$text; return $this; } /** * Getter method of the tags property * @return array */ public function getTags() { return $this->tags; } /** * Setter method of the tags property * @param array $value - The new value of the property * @return valami\tartalom\menedzser\Content */ public function setTags(array $tags) { $this->tags = $tags; return $this; } } |
(A félig angol félig magyar dokumentáció rosszul néz ki, de két kattintással generáltam)
Ez utóbbi folyamatot veszi át a következő kód:
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 | <?php /** * GS-Generator * This tool can be used to create getter and setter method stubs for any class. * Usage: * php GS-Generator.php "class_file_name" <optinal flags> * Optional flags: * -c = Copy to clipboard instead of printing to file (Windows only, requires MS Word) * -d = Debug mode - create assertions for setter function with native types * -gv [public|private|protected] = The visibility of the getter methods * -sv [public|private|protected] = The visibility of the setter methods * @version 1.0 beta * @author BlackY */ /** * The basic level of indention used (default: 1 tabs) * @var string */ $indention = str_repeat("\t", 1); /** * The visibility of getter methods * @var string */ $getterVisibility = ($index = array_search('-gv', $argv)) !== false ? $argv[$index + 1] : 'public'; /** * The visibility of the setter methods * @var string */ $setterVisibility = ($index = array_search('-sv', $argv)) !== false ? $argv[$index + 1] : 'public'; /** * A flag indicating whether to include assertions in the produces code * @var bool */ $includeAssert = in_array('-d', $argv); /** * A list of "black listed" types: those that require no type hinting. * Array is not listed here, as arrays are handled another way. * @var array */ $typeBlackList = array( 'int', 'integer', 'bool', 'boolean', 'float', 'double', 'real', 'string', 'callback', 'scalar', 'var', 'unknown' ); /** * A list of native data types that need no casting */ $noCast = array('callback', 'scalar', 'var', 'unknown', 'resource'); /** * The list of type checking functions to use in the assertions. * @var array */ $typeCheckFunctions = array( 'int' => 'is_int', 'integer' => 'is_int', 'bool' => 'is_bool', 'boolean' => 'is_bool', 'float' => 'is_float', 'double' => 'is_float', 'real' => 'is_float', 'string' => 'is_string', 'resource' => 'is_resource', 'callback' => 'is_callable', 'scalar' => 'is_scalar' ); /** * The name of the input file * @var string */ $fileName = null; /* Find the input file in the arguments */ foreach($argv as $arg) { if(basename(__FILE__) != basename($arg) && file_exists($arg) && is_readable($arg)) { $fileName = $arg; } } if(!$fileName) { die('Input file not specified or not found/readable!'); } chdir(dirname($fileName)); /** Get the list of classes that need getter/setter methods */ $old_classes = get_declared_classes(); if(!include_once($fileName)) { die('Input file inclusion failed.'); } $new_classes = get_declared_classes(); $classes = array_diff($new_classes, $old_classes); if(!$classes) { die('No class definition in input file!'); } /* Generate the methods */ foreach($classes as $class) { $reflection = new ReflectionClass($class); $source = ''; foreach($reflection->getProperties() as $property) { $name = $property->getName(); $docComment = $property->getDocComment(); $type = 'unknown'; if(preg_match('/@var\s+(.*)\b/i', $docComment, $regs)) { $type = $regs[1]; } $hasMethods = $reflection->hasMethod('get' . $name) && $reflection->hasMethod('set' . $name); $nonProtected = $property->isPublic(); $isStatic = $property->isStatic(); if($hasMethods || $nonProtected || $isStatic) { continue; } /* Getter method */ $source .= $indention . '/**' . PHP_EOL; $source .= $indention . ' * Getter method of the ' . $name . ' property' . PHP_EOL; $source .= $indention . ' * @return ' . $type . PHP_EOL; $source .= $indention . '*/' . PHP_EOL; if(strtolower($type) == 'bool' || strtolower($type) == 'boolean') { $source .= $indention . $getterVisibility . ' function is' . ucfirst($name) . '()' . PHP_EOL; } else { $source .= $indention . $getterVisibility . ' function get' . ucfirst($name) . '()' . PHP_EOL; } $source .= $indention . '{' . PHP_EOL; $source .= $indention . "\t" . 'return $this->' . $name . ';' . PHP_EOL; $source .= $indention . '}' . PHP_EOL . PHP_EOL; /* Setter method */ $source .= $indention . '/**' . PHP_EOL; $source .= $indention . ' * Setter method of the ' . $name . ' property' . PHP_EOL; $source .= $indention . ' * @param ' . $type . ' $value - The new value of the property' . PHP_EOL; $source .= $indention . ' * @return ' . $reflection->getName() . PHP_EOL; $source .= $indention . '*/' . PHP_EOL; $source .= $indention . $setterVisibility . ' function set' . ucfirst($name) . '('; $cast = ''; $assert = ''; if(in_array(strtolower($type), $typeBlackList)) { $source .= '$' . $name; if(!in_array(strtolower($type), $noCast)) { $cast = '(' . $type . ')'; } if($includeAssert && isset($typeCheckFunctions[strtolower($type)])) { $assert = $indention . "\t" . 'assert(\'' . $typeCheckFunctions[strtolower($type)] . '($' . $name . ')\')' . PHP_EOL; } } elseif(strtolower($type) == 'array') { $source .= 'array $' . $name; } else { $source .= $type . ' $' . $name; } $source .= ')' . PHP_EOL; $source .= $indention . '{' . PHP_EOL; $source .= $assert; $source .= $indention . "\t" . '$this->' . $name . ' = '. $cast . '$' . $name . ';' . PHP_EOL; $source .= $indention . "\t" . 'return $this;' . PHP_EOL; $source .= $indention . '}' . PHP_EOL . PHP_EOL; } $filename = dirname(__FILE__) . DIRECTORY_SEPARATOR . basename($reflection->getName() . '_generated.php'); file_put_contents($filename, $source); if(class_exists('COM') && in_array('-c', $argv) && count($classes) == 1) { try { $com = new COM('Word.Application'); $com->Visible = false; $com->Documents->Add(); $com->Selection->TypeText($source); $com->Selection->WholeStory(); $com->Selection->Copy(); $com->Quit(false); unlink($filename); } catch(Exception $x) { try { $com->Quit(false); } catch(Exception $x) {} } } } |
A feladatunk össz-vissz annyi, hogy a fenti – első – Content osztálynak megfelelően leírjuk az osztályunkat: a docCommentekben legyen ott a @var direktíva.
Ezután – mindent alapbeállításon hagyva – a kód a
php GS-Generator.php myClassFile.php
utasítást kiadva létrehozza a metódusok forráskódját és elmenti az <osztálynév>_generated.php névvel létrehozott fájlokban. (Ha a bemeneti fájlban több osztály van, több ilyen fájl jön létre). Ezt copy-pastelve az osztály törzsébe, kész is vagyunk.
A kód automatikusan generál type hinteket az osztályokhoz és a tömb típushoz, a natív típusokat pedig az elhelyezésük előtt converálja (castolja) a megfelelő típusra. Ezzel az egyetlen probléma az lehet, ha egy tulajdonság vagy egy objektum vagy null értéket vehet fel (a fenti példában például már törölve lett a cikk írója vagy egyéb okból nem elérhető), a null érték miatt a PHP hibát ad. Ezt áthidaló bevezettem a var „típust”, ezt használva nincs castolás és típus súgás (sajnos típus biztonság sem). (Ezeket a setterek érdemes kézzel átírni, hogy is_nul() és instanceof-al eldöntsék, helyes-e az érték, mielőtt beírják az értéket) Újra átolvasva a PHP manualt észrevettem a kitételt, hogy a
<típusnév> $valtozo = null
paraméter-definíció esetén adható null érték a változónak. Az oldal végén levő új változat már használja ezt a lehetőséget.
A natív adattípusokon (bool, int, float, string) kívül használhatjuk még a scalar (bármelyik skaláris érték) illetve a callback (hívható) típusokat. Az elkészült docCommentekben találkozhatunk még az unknown típussal, ezt használja a rendszer, ha nem volt típus jelölve a tulajdonságnál.A lap végén levő frissített kód hiányzó típusmegadás esetén nem hoz végre settert/gettert.
Azokhoz a tulajdonságokhoz, amelyek már rendelkeznek getter és setter függvénnyel vagy (bármilyen oknál fogva) publikusak nem hoz létre metódusokat, így egy új tulajdonság felvitelekor csak az azok kezelését biztosító függvényeket hozza létre.
A fentieken felül még néhány további opciót is kezel a rendszer, ezek parancssori paraméterrel kapcsolhatók:
- -gv [public|protected|private] – A getter metódusok láthatóságát állíthatjuk be
- -sv [public|protected|private] – A setter metódusok láthatósága
- -d – Debug mód: assert()-ek hozzáadása a kódhoz, így a natív adattípusok is ellenőrzésre kerülnek. Az éles szerverre kerülés előtt generáljuk újra a metódusokat a kapcsoló nélkül!
- -c – Csak Windows rendszeren, telepített Microsoft Word-del (csak ez utóbbi COM objektumain keresztül tudok kommunikálni a vágólappal. Ha tudsz jobb megoldást, szólj!)! Az elkészült kódot nem fájlba menti, hanem a vágólapra másolja
Utóbbi opció azért került bele, hogy a php fájlok helyi menüjéhez hozzá tudjak rendelni egy új elemet, ami legenerálja a metódusokat és azok kódját a vágólapra teszi. Ezt a következő képpen tehetjük meg: indítsuk el a regedit-et. A bal oldali fában keressük meg a HKEY_LOCAL_MACHINE \ SOFTWARE \ Classes \ .php \ Shell kulcsot. (Ha valamelyik nem létezik, jobb klikk a szülőn, új, majd kulcs).
Itt hozzunk létre egy kulcsot azzal a névvel, amilyen nevet a helyi menüben látni szeretnénk. Nálam egy „Metódusok generálása GSGenerator-ral (Assert: On)” ill. „Metódusok generálása GSGenerator-ral (Assert: Off)” lett (két külön kulcs). A létrehozott kulcson belül hozzunk létre egy új kulcsot „Command” néven, majd kattintsunk rá.
A jobb oldalon az (Alapértelmezett) értékre kattintva írjuk be a parancsot, amit futtatni szeretnénk:
"C:\A php útvonala\php-win.exe" "C:\A GSGenerator.php fájl útvonala" [flagek] "%1"
A [flagek] helyére természetesen behelyettesítve a fentebb írt paramétereket. Nálam a két kulcs a következőképp néz ki:
"C:\Program Files\xampplite\php\php-win.exe" "C:\Documents and Settings\Rendszergazda\Asztal\GS-Generator.php" -c -d "%1"
és
"C:\Program Files\xampplite\php\php-win.exe" "C:\Documents and Settings\Rendszergazda\Asztal\GS-Generator.php" -c "%1"
Remélem másnak is hasznos lesz ez a rövid script és leírás. Jó munkát!
Módosítás:
Ahogy azt már fentebb írtam a kivágott részek után, készítettem egy frisebb verziót (letisztultabb lett a kódja stb.)
A paraméterézében is történt néhány változás (ehhez mérten a Registry-be írt paramétereket is változnak).
Az új használat (<fájlnév> az a fájlnév, amelyen a generálót elmentettük):
php <fájlnév> [<kapcsolók,paraméterek>]
Az új kód működik minden parancssori paraméter nélkül is, ha így indítjuk, a standard inputról olvassa a forráskódot és a standard outputra küldi ki az eredményt.
A –input <fájlnév> kapcsoló használatával elérhetjük, hogy a standard input helyett a fájlnév tartalmát értelmezze.
A -f kapcsoló segítségével az elkészült kódokat fájlba írja ki, ezek elnevezesét a –template „fájlnév_sablon” paraméterrel módosíthatjuk (ebben az osztálynév (a névtér nem) is behelyettesítésre kerül a %1$s helyekre).
A láthatóságot ezentúl a –getter <public|protected|private> és –setter <public|protected|private> paraméterekkel állíthatjuk.
Megadhatjuk, hogy hányszoros behúzást használjon a rendszer az –indention <szám> paraméterrel, továbbá az –indentionString „<string>” paraméterrel beállíthatjuk, hogy az egy szintű behúzás mit jelentsen (space és tab indentálás így cserélgethető). Így például a négy szóközzel való, két szintű indentálást a
php <fájlnév> –indentionString " " –indention 2
utasítással érhetjük el.
Természetesen megmaradt az assert hívások és az automatikus castolás lehetősége is, ezeket a -a ill. -ac kapcsolókkal érhetjük el. Hiba – vagy figyelmezetések – esetén a kód a standard error csatornára ír ki üzeneteket, ha ezt el akarjuk tüntetni, a -s kapcsolót állítsuk be. Végül a korábbi verzióból megismert vágólapra másolás is visszatért, ezt a -c kapcsoló állításával kapcsolhatjuk be. Ha a -c és -s kapcsolót is használjuk, sikeres lefutás végén egy felbukkanó ablak értesít arról, hogy végzett. (Ez esetemben hasznos, a fenti registry módosítással ez lett az alapvető akció a .php fájl típusoknál, így az Eclipse helyi menüjében az Open With -> System Editorral tudom futtatni, ezért kellett az értesítő)
Fontos változás az előző verzióhoz képest, hogy ez a fájlban csak egy osztályt kezel (elkerülve hogy egy teljes keretrendszert megpróbáljon átírni), így vagy csak egy osztályt deklaráljunk a fájlban, vagy használjuk a –class <osztálynév> paramétert.
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 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | <?php /** * Generate Getter and Setter methods * This utility can be used to create getter and setter methods for any class. * -s (Silent mode) * -f (Output file instead of writing to STDOUT) * -c (Copy source code instead of writing to STDOUT) * -a (Add assertions) * -ac (Add casts) * --template (The file naming scheme) * --input (Input file) * --getter <private|protected|public> - The visibility of the getter functions * --setter <private|protected|public> - The visibility of the setter functions * --indention - The number of tabs before each line * --indentionString - The string used for indention * @author Szigeti Márton Levente <blacky@invitel.hu> * @package ggsm */ $indent = cliParameter('indentionString', "\t"); $getterMethodDocCommentTemplate = explode(PHP_EOL, <<<TEMPLATE /** * Getter method of the %1\$s property * @return %2\$s The value of the property */ TEMPLATE ); $setterMethodDocCommentTemplate = explode(PHP_EOL, <<<TEMPLATE /** * Setter method of the %1\$s property * @param %6\$s%4\$s%2\$s \$%1\$s%5\$s The new value of the %1\$s property * @return %3\$s The instance containing the property */ TEMPLATE ); $getterMethodTemplate = explode(PHP_EOL, <<<TEMPLATE %2\$s function %4\$s%1\$s() { {$indent}return \$this->%3\$s; } TEMPLATE ); $setterMethodTemplate = explode(PHP_EOL, <<<TEMPLATE %2\$s function %1\$s(%5\$s%4\$s\$%3\$s%6\$s) { {$indent}%7\$s\$this->%3\$s = %4\$s%8\$s$%3\$s; } TEMPLATE ); /** No editable parts below */ function getValidator($type) { if(!isNative($type)) { return ''; } else { $validators = array( 'bool' => 'is_bool', 'boolean' => 'is_bool', 'int' => 'is_int', 'integer' => 'is_int', 'float' => 'is_float', 'double' => 'is_float', 'real' => 'is_float', 'string' => 'is_string', 'object' => 'is_object', 'number' => 'is_numeric', 'callback' => 'is_callable'); if(isset($validators[strtolower($type)])) { return $validators[strtolower($type)]; } return null; } } function getCast($type) { if(!isNative($type)) { return ''; } else { $casts = array( 'bool' => '(bool)', 'boolean' => '(boolean)', 'int' => '(int)', 'integer' => '(integer)', 'float' => '(float)', 'double' => '(double)', 'real' => '(real)', 'string' => '(string)', 'object' => '(object)'); if(isset($casts[strtolower($type)])) { return $casts[strtolower($type)]; } return null; } } function isNative($type) { return in_array(strtolower(extractBaseType($type)), array( 'bool', 'boolean', 'int', 'integer', 'float', 'double', 'real', 'string', 'object', /* Pseudo-types */ 'number', 'callback' )); } function extractType($comment) { if(preg_match('/@var\s+([&\\\\\w?]+)/', $comment, $regs)) { return $regs[1]; } return null; } function extractBaseType($type, $classNamespace = null) { $type = trim($type, '?&'); if(!is_null($classNamespace)) { if(dirname($type) == $classNamespace) { $type = basename($type); } } return $type; } function isReference($type) { return $type{0} == '&'; } function isNullable($type) { return substr($type, -1) == '?'; } function cliParameter($parameter, $default = null) { global $argv; $parameter = strtolower($parameter); foreach($argv as $index => $argument) { if(strtolower($argument) == '--' . $parameter) { if(isset($argv[$index + 1]) && $argv[$index + 1]{0} != '-') { return $argv[$index + 1]; } } } return $default; } function cliFlagSet($flag) { global $argv; foreach($argv as $argument) { if($argument == '-' . $flag || $argument == '/' . $flag) { return true; } } return false; } function println($message, $file = STDOUT) { if(!cliFlagSet('s')) { fwrite($file, $message . PHP_EOL); } } function ifExit($condition, $message = null, $code = null) { if($condition) { if(!is_null($message)) { println($message, STDERR); } exit($code); } } function gsErrorHandler($errno, $errstr, $file, $line) { println(sprintf('%3$s[%4$d]: (%1$d) %2$s', $errno, $errstr, basename($file), $line), STDERR); } $inputFile = cliParameter('input', null); $workingDirectory = getcwd(); if(!$inputFile) { println('Starting in interactive mode (Hit CTRL+Z to quit)', STDERR); $sourceCode = ''; while(!feof(STDIN)) { $chunk = fread(STDIN, 8192); $sourceCode .= $chunk; } } else { $condition = !(file_exists($inputFile) && is_readable($inputFile)); ifExit($condition, sprintf('The specified input file can not be found: %s', $inputFile) ,1); chdir(dirname($inputFile)); ini_set('include_path', '.' . PATH_SEPARATOR . ini_get('include_path')); $sourceCode = file_get_contents($inputFile); } $classesBefore = get_declared_classes(); ifExit(eval('?>' . $sourceCode) === false, 'Source code could not be parsed', 2); chdir($workingDirectory); $classesAfter = get_declared_classes(); $classes = array_values(array_diff($classesAfter, $classesBefore)); ifExit(count($classes) == 0, 'Source code did not contain class declarations. Terminating.', 4); $class = $classes[0]; ifExit((count($classes) > 1) && ($class = cliParameter('class', false)) === false, 'Source code contained more than one class declaration. Use --class <className>. Terminating.', 5); /* Prepare templates */ $function = create_function('&$line', '$line = rtrim(str_repeat(cliParameter("indentionString", "\t"), cliParameter("indention", 1)) . $line);'); array_walk($getterMethodDocCommentTemplate, $function); array_walk($setterMethodDocCommentTemplate, $function); array_walk($getterMethodTemplate, $function); array_walk($setterMethodTemplate, $function); $getterMethodDocCommentTemplate = implode(PHP_EOL, $getterMethodDocCommentTemplate); $setterMethodDocCommentTemplate = implode(PHP_EOL, $setterMethodDocCommentTemplate); $getterMethodTemplate = implode(PHP_EOL, $getterMethodTemplate); $setterMethodTemplate = implode(PHP_EOL, $setterMethodTemplate); /* Preparing templates end */ $reflection = new ReflectionClass($class); $properties = $reflection->getProperties(); $propertiesSorted = array(); foreach($properties as $property) { $propertiesSorted[$property->getName()] = $property; } ksort($propertiesSorted); $properties = $propertiesSorted; /* Create source code */ $source = ''; $useStatements = ''; $name = explode('\\', $reflection->getName()); $classNamespace = version_compare(phpversion(), '5.3.0') ? implode('\\', array_slice($name, 0, count($name) - 1)) : null; foreach($propertiesSorted as $property) { $setterName = 'set' . ucfirst($property->getName()); $getterName = 'get' . ucfirst($property->getName()); if(($reflection->hasMethod($setterName) && $reflection->hasMethod($getterName)) || $property->isPublic()) { continue; } $type = extractType($property->getDocComment()); if(is_null($type)) { continue; } $name = $property->getName(); $baseType = extractBaseType($type, $classNamespace); $classType = extractBaseType($reflection->getName(), $classNamespace); $getterVisibility = cliParameter('getter', 'public'); $setterVisibility = cliParameter('setter', 'public'); $cast = cliFlagSet('ac', false) && isNative($type) ? getCast(extractBaseType($type)) : ''; $referenceSign = isReference($type) ? '&' : ''; if($referenceSign) { $cast = ''; } $nullStart = isNullable($type) ? '[' : ''; $nullEnd = isNullable($type) ? ' = null] ' : ''; $nullDefault = isNullable($type) ? ' = null' : ''; $typeHint = ''; if(!isNative($type)) { $namespace = dirname(extractBaseType($type)); if(strtolower(extractBaseType($type)) != 'array' && $namespace != '.' && $classNamespace != $namespace) { $useStatements .= 'use ' . extractBaseType($type) . ';' . PHP_EOL; } $typeHint = basename(extractBaseType($type)) . ' '; } $assertion = cliFlagSet('a', false) && isNative($type) ? "assert('" . getValidator(extractBaseType($type)) . "(\$" . $property->getName() . ")');" . PHP_EOL . str_repeat(cliParameter('indentionString', "\t"), cliParameter('indention', 1) + 1) : ''; $source .= sprintf($getterMethodDocCommentTemplate, $name, $baseType); $source .= sprintf($getterMethodTemplate, $getterName, $getterVisibility, $name, $referenceSign); $source .= sprintf($setterMethodDocCommentTemplate, $name, $baseType, $classType, $referenceSign, $nullEnd, $nullStart); $source .= sprintf($setterMethodTemplate, $setterName, $setterVisibility, $name, $referenceSign, $typeHint, $nullDefault, $assertion, $cast); } $source = $useStatements . PHP_EOL . $source; if(cliFlagSet('f')) { $template = cliParameter('template', '%1$s_generated.php'); file_put_contents(sprintf($template, extractBaseType($class, $classNamespace)), $source); } elseif(class_exists('COM') && cliFlagSet('c')) { try { $wordCom = new COM('Word.Application'); $wordCom->Visible = false; $wordCom->Documents->Add(); $wordCom->Selection->TypeText($source); $wordCom->Selection->WholeStory(); $wordCom->Selection->Copy(); $wordCom->Quit(false); if(cliFlagSet('s')) { $message = 'Getters and setter copied to clipboard'; $title = 'Finished'; $scriptCom = new COM('WScript.Shell'); $scriptCom->Popup($message, 0, $title, 0); } } catch(Exception $x) { try { $wordCom->Quit(false); } catch(Exception $x) {} exit(5); } } else { echo $source; } exit(0); |
Ez a __get() __set() helyettesítés eléggé ki lett vesézve, bár biztosan tömör és száraz sokaknak, mégis többet ad, mint a legtöbb példa ;) thx