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:

<?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:

<?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:

<?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: > Assert: On"C:\Program Files\xampplite\php\php-win.exe" "C:\Documents and Settings\Rendszergazda\Asztal\GS-Generator.php" -c -d "%1"

és > Assert: Off "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.

<?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);
Harder

Harder

Profil

Korábbi hozzászólások (1)

A régi blogon érkezett hozzászólások archívuma. Új hozzászólást már nem lehet írni.

  1. cyruswww.cyrusmagus.hu

    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

Van hozzáfűznivalód? Írj nekem közvetlenül.

Kapcsolat