Skip to content

Instantly share code, notes, and snippets.

@claussni
Created March 7, 2010 19:47
Show Gist options
  • Save claussni/324594 to your computer and use it in GitHub Desktop.
Save claussni/324594 to your computer and use it in GitHub Desktop.
Annotations and code generation
<?php
// set include path to library
set_include_path(implode(PATH_SEPARATOR, array(
'/opt/ZendFramework-1.10.1/library',
get_include_path(),
dirname(__FILE__)
)));
require_once 'Zend/Loader/Autoloader.php';
$autoloader = Zend_Loader_Autoloader::getInstance();
interface IJsonEncodeable {
public function getJsonString();
}
class JsonEncodeable implements IJsonEncodeable {
public function getJsonString() {
return json_encode($this);
}
}
class HelloWorld {
public function sayHello($to) {
echo "Hello, $to!\n";
}
}
function stripUnderscores($string) {
return preg_replace('/^(_)*/', '', $string);
}
function getTypeCheckCode($propertyName, $propertyType) {
$typecheck = '';
if (null !== $propertyType) {
switch ($propertyType) {
case 'string' :
$typecheck = "if (! is_string(\$$propertyName)) " .
"throw InvalidArgumentException('Expected given value to be of type string.');\n";
break;
case 'int' :
$typecheck = "if (! is_int(\$$propertyName)) " .
"throw InvalidArgumentException('Expected given value to be of type int.');\n";
break;
case 'array' :
$typecheck = "if (! is_array(\$$propertyName)) " .
"throw InvalidArgumentException('Expected given value to be of type array.');\n";
break;
default:
break;
}
}
return $typecheck;
}
function getSetterCode($setterName, $propertyName, $propertyNameNormalized, $phpType = null) {
$body = '$this->' . $propertyName . ' = $' . $propertyNameNormalized . '; return $this;';
$parameter['name'] = $propertyNameNormalized;
if (null !== $phpType) {
$typecheck = getTypeCheckCode($propertyName, $phpType);
$body = $typecheck . $body;
if ('' === $typecheck) {
$parameter['type'] = $phpType;
}
}
return new Zend_CodeGenerator_Php_Method(array(
'name' => $setterName,
'parameters' => array($parameter),
'body' => $body
));
}
function getGetterCode($getterName, $propertyName, $propertyNameNormalized, $phpType = null) {
$body = 'return $this->' . $propertyName . ';';
return new Zend_CodeGenerator_Php_Method(array(
'name' => $getterName,
'body' => $body
));
}
function getPropertyType(Zend_CodeGenerator_Php_Property $property) {
$docblock = $property->getDocblock();
if (null !== $docblock) {
$tags = $docblock->getTags();
foreach ($tags as $tag) {
if ($tag->getName() === 'var') {
return $tag->getDescription();
}
}
}
}
function getGenerateAnnotations(Zend_CodeGenerator_Php_Property $property) {
$result = array();
$docblock = $property->getDocblock();
if (null !== $docblock) {
$tags = $docblock->getTags('generate');
foreach ($tags as $tag) {
$result[] = $tag->getDescription();
}
}
return $result;
}
function handleAccessors(Zend_CodeGenerator_Php_Class $class) {
foreach ($class->getProperties() as $property) {
if ('private' !== $property->getVisibility()) continue;
$propertyName = $property->getName();
$propertyNameNormalized = stripUnderscores($propertyName);
$setterName = 'set' . ucfirst($propertyNameNormalized);
$getterName = 'get' . ucfirst($propertyNameNormalized);
$propertyType = getPropertyType($property);
$generateAnnotations = getGenerateAnnotations($property);
if ((in_array('set', $generateAnnotations)) and (! $class->hasMethod($setterName))) {
$class->setMethod(getSetterCode($setterName, $propertyName, $propertyNameNormalized, $propertyType));
}
if ((in_array('get', $generateAnnotations)) and (! $class->hasMethod($getterName))) {
$class->setMethod(getGetterCode($getterName, $propertyName, $propertyNameNormalized, $propertyType));
}
}
}
function importInterfaceImplementation(
Zend_CodeGenerator_Php_Class $class,
Zend_CodeGenerator_Php_Class $interface,
Zend_CodeGenerator_Php_Class $implementation) {
foreach ($interface->getMethods() as $interfaceMethod) {
$implMethod = $implementation->getMethod($interfaceMethod->getName());
$class->setMethod($implMethod);
}
}
function handleImports(Zend_CodeGenerator_Php_Class $class) {
$docblock = $class->getDocblock();
if (null === $docblock) return;
$importTags = $docblock->getTags('import');
foreach ($importTags as $importTag) {
$importClassName = $importTag->getDescription();
$importClass = Zend_CodeGenerator_Php_Class::fromReflection(
new Zend_Reflection_Class($importClassName));
$importInterfaces = $importClass->getImplementedInterfaces();
if (empty($importInterfaces)) {
foreach ($importClass->getMethods() as $method) {
$class->setMethod($method);
}
} else {
$implementedInterfaces = $class->getImplementedInterfaces();
$class->setImplementedInterfaces(array_merge($implementedInterfaces, $importInterfaces));
foreach ($importInterfaces as $importInterfaceName) {
$importInterface = Zend_CodeGenerator_Php_Class::fromReflection(
new Zend_Reflection_Class($importInterfaceName));
importInterfaceImplementation($class, $importInterface, $importClass);
}
}
}
}
$filename = 'Model.php';
$classname = 'Model';
$generator = Zend_CodeGenerator_Php_File::fromReflectedFileName($filename);
$class = $generator->getClass($classname);
handleAccessors($class);
handleImports($class);
echo $class;
<?php
/**
* @import JsonEncodeable
* @import HelloWorld
*/
class Model
{
/**
* @generate set
* @generate get
* @var string
*/
private $_firstName;
/**
* @generate set
* @generate get
* @var string
*/
private $_lastName;
/**
* @generate get
* @var string
*/
private $_email;
/**
* @var int
*/
private $_age;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment