protected function injectToSetter(GClass $gClass) { $setter = 'set' . $this->relation->getSourceMethodName(); if (!$gClass->hasOwnMethod($setter)) { throw new \RuntimeException('in der Klasse kann ' . $setter . ' nicht gefunden werden. Womöglich muss der Setter vererbt werden'); } else { $setter = $gClass->getMethod($setter); } if ($this->relation->isTargetNullable()) { $firstParam = current($setter->getParameters()); $firstParam->setOptional(TRUE)->setDefault(NULL); } if ($this->relation->shouldUpdateOtherSide()) { // wenn die Relation bidrektional ist muss der normale setter auf der Inverse side addXXX auf der aufrufen // das ist aber gar nicht so trivial, weil wie wird removed? // before('return $this').insert(...) $body = $setter->getBodyCode(); $lastLine = array_pop($body); if (\Psc\Preg::match($lastLine, '/^\\s*return \\$this;$/') <= 0) { throw new \Psc\Exception('EntityRelationInterfaceBuilder möchte den Setter: ' . $setter->getName() . ' für ' . $gClass . ' ergänzen, aber der Body code scheint kein autoGenererierter zu sein.'); } $body[] = \Psc\TPL\TPL::miniTemplate(($this->relation->isTargetNullable() ? 'if (isset($%paramName%)) ' : NULL) . '$%paramName%->add%otherMethodName%($this);' . "\n", array('paramName' => $this->relation->getTarget()->getParamName(), 'otherMethodName' => $this->relation->getSource()->getMethodName('singular'))); $body[] = $lastLine; $setter->setBodyCode($body); } }
/** * @return Webforge\Common\System\File */ protected function getGClassFromFile() { $project = \Psc\PSC::getProject(); $gClass = new GClass(Code::mapFileToClass($this->file, $project->dir('lib'))); $gClass->setSrcFileName((string) $this->file); // damit wir wirklich fremde sourcen angeben können return $gClass; }
public function testMethodGenerationAcceptance() { $gClass = new GClass('ToBeStubbedClass'); $gClass->setParentClass(new GClass(__NAMESPACE__ . '\\StubTestAbstractClass')); $gClass->addInterface(new GClass(__NAMESPACE__ . '\\AnInterface')); $gClass->createAbstractMethodStubs(); $this->test->gClass($gClass)->hasMethod('getName')->hasMethod('implementIt')->hasMethod('implementItFromParent')->hasMethod('generateDependency', array('deps', 'gClass')); }
public function testPrependToNotEmptyConstructor() { // regression, weil das irgendwie nicht ging, hää $gClass = new GClass('NoProperties'); $gClass->createMethod('__construct', array(new GParameter('someP1'))); $this->extension->setGenerateInConstructor(0)->compile($gClass); $constructor = $this->test->gClass($gClass)->hasMethod('__construct', array('oid', 'someP1'))->get(); }
public function testAlreadyMarkedClassGetsNotMarked() { $gClass = new GClass('MarkedClass'); $gClass->createDocBlock()->addAnnotation(\Psc\Code\Compile\Annotations\Compiled::create()); // erstellen hier darf jetzt keine neue annotation in out erstellen $ext = new MarkCompiledExtension(); $ext->compile($gClass); $this->assertCount(1, $gClass->getDocBlock()->getAnnotations('Psc\\Code\\Compile\\Annotations\\Compiled'), 'Anzahl der @Compiled Annotations ist falsch!'); }
protected function getUseClassWriter() { $gClass = new GClass('TestClass'); $gClass->setNamespace('\\Psc\\habe\\keinen'); $writer = new ClassWriter(); $writer->setClass($gClass); $writer->addImport(new GClass('Webforge\\Common\\System\\File'), 'SystemFile'); $writer->addImport(new GClass('Psc\\Doctrine\\Helper'), 'DoctrineHelper'); return $writer; }
public function loadFixtureGClass($className) { $file = $this->getFile('fixture.' . $className . '.php'); require_once $file; $gClass = GClass::factory('Psc\\Code\\Compile\\Tests\\' . $className); return $gClass; }
/** * Gibt den Namen der EntityRelationMeta zurück * * @return string */ public function getName() { if (isset($this->alias)) { return $this->alias; } else { return $this->gClass->getClassName(); } }
protected function getCClass(File $out, $className = 'NormalClass') { // das hier ist nicht wahr //$this->assertFalse(class_exists('Psc\System\Console\NormalClass',FALSE)); // weil der commandTester die Klasse lädt (bzw der Command) müssen wir die $out file hier umbenennen um das Ergebnis testen zu können $ccName = 'Compiled' . $className; $out->writeContents(str_replace('class ' . $className . ' ', 'class ' . $ccName . ' ', $out->getContents())); require $out; $gClass = GClass::factory('Psc\\System\\Console\\' . $ccName); return $gClass; }
protected function execute(InputInterface $input, OutputInterface $output) { $overwrite = $input->getOption('overwrite') ? ClassWriter::OVERWRITE : NULL; $controllerName = $input->getArgument('name'); $entityClass = $this->getDoctrineModule()->getEntityName($controllerName); $gClass = new GClass(); $gClass->setClassName($controllerName . 'Controller'); $gClass->setNamespace($this->getProject()->getNamespace() . '\\Controllers'); // siehe auch EntityService $gClass->setParentClass(new GClass('Psc\\CMS\\Controller\\AbstractEntityController')); $classBuilder = new ClassBuilder($gClass); $classBuilder->createProtectedMethod('setUp', array(), array("parent::setUp();")); $classBuilder->createMethod('getEntityName', array(), array(sprintf("return '%s';", $entityClass))); $imports = array(new GClass($entityClass)); $classWriter = new ClassWriter(); $classWriter->setClass($gClass); $classWriter->write($file = $this->getProject()->getClassFile($gClass), $imports, $overwrite); $output->writeLn('Controller in Datei: "' . $file . '" geschrieben'); return 0; }
/** * @return Webforge\Common\System\File */ public function getTestFile() { /* zuerst setzen wir den ns in einen relativen pfad um */ $file = Code::mapClassToFile($this->class->getName(), NULL); /* entfernt das erste und zweite verzeichnis (das erste ist der .)*/ $file->getDirectory()->slice(2); /* wir fügen den rest des relativen Verzeichnisses an das tests-Verzeichnis an */ $dir = clone $this->dir; $dir->append($file->getDirectory()); $file = new File($dir, $this->class->getClassName() . 'Test'); $file->setExtension('.php'); return $file; }
public function __call($method, $args) { $prop = mb_strtolower(mb_substr($method, 3, 1)) . mb_substr($method, 4); // ucfirst in mb_string /* getter der nicht implementiert ist */ if (mb_strpos($method, 'get') === 0) { if ($this->annotationClass->hasProperty($prop)) { return $this->annotation->{$prop}; } else { throw new MissingPropertyException($prop, 'Annotation: ' . $this->annotationClass->getFQN() . " hat kein Feld '" . $prop . "'"); } } /* setter der nicht implementiert ist */ if (mb_strpos($method, 'set') === 0) { if ($this->annotationClass->hasProperty($prop)) { $this->annotation->{$prop} = $args[0]; return $this; } else { throw new MissingPropertyException($prop, 'Annotation: ' . $this->annotationClass->getFQN() . " hat kein Feld '" . $prop . "'"); } } throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()'); }
public function compile(GClass $gClass, $flags = 0x0) { $c = 'Psc\\Code\\Compile\\Annotations\\Compiled'; if (!$gClass->hasDocBlock() || !$gClass->getDocBlock()->hasAnnotation($c)) { // @FIXME hasAnnotation kann falsch sein! /* erstelle einen DocBlock / modifiziere den DocBlock von gClass */ if (!$gClass->hasDocBlock()) { $gClass->createDocBlock(); } $gClass->getDocBlock()->addAnnotation($c::create()); } }
public function testStub() { $gClass = new GClass('Psc\\Code\\Generate\\MyTestClass'); $out = $this->newFile('MyTestClassTest.php'); $out->delete(); $tc = $this->getMock('Psc\\Code\\Generate\\TestCreater', array('getTestFile'), array($gClass)); $tc->expects($this->once())->method('getTestFile')->will($this->returnValue($out)); $outTc = $tc->create(); $this->assertSame($out, $outTc); // checkt ob unser mock geklappt hat require $out; $this->assertTrue(class_exists('Psc\\Code\\Generate\\MyTestClassTest', FALSE)); $test = GClass::factory('Psc\\Code\\Generate\\MyTestClassTest'); $db = $test->getDocBlock(); $this->assertContains('@group class:Psc\\Code\\Generate\\MyTestClass', $db->toString()); $this->assertTrue($test->hasMethod('setUp'), 'methode setUp existiert nicht im Test'); $this->assertTrue($test->hasMethod('testAcceptance'), 'methode testAcceptance existiert nicht im Test'); $this->assertEquals('Psc\\Code\\Test\\Base', $test->getParentClass()->getFQN()); // achtung das hier ist kein instanceof }
public function createClassMetadata(GClass $gClass) { // da wir gClass mehrmals im Test evalen könnten, erzeugen wir einen unique hash für den classname und übergeben den // der class metadata $className = uniqid($gClass->getClassName()); $gClass->setClassName($className); $gClass->createDocBlock()->addAnnotation(Annotation::createDC('Entity')); $classWriter = new ClassWriter($gClass); $classWriter->setUseStyle('lines'); $classWriter->addImport(new GClass('Doctrine\\ORM\\Mapping'), 'ORM'); // braucht einen AnnotationReader nicht SimpleAnnotationReader $classWriter->write($file = $this->newFile('entity.' . $gClass->getClassName() . '.php')); require $file; $cm = new ClassMetadata($gClass->getFQN()); $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService()); $this->annotationDriver->loadMetadataForClass($gClass->getFQN(), $cm); $file->delete(); return $cm; }
protected function getCompiler() { $input = $this->execInput; $output = $this->execOutput; $class = $input->getArgument('class'); $file = $this->getInFile(); if ($class === 'inFile') { $parser = new \Psc\Doctrine\PhpParser(); if (($class = $parser->findFirstClass((string) $file)) == NULL) { throw new \Psc\Exception('inFile kann keine Klasse ermitteln. Es wurden keine Klassen in der Datei gefunden'); } } if (!class_exists($class, FALSE)) { require $file; } if (!class_exists($class, FALSE)) { throw new \InvalidArgumentException('Klasse ' . $class . ' konnte nicht in Datei ' . $file . ' gefunden werden'); } $gClass = GClass::factory($class); $classReader = new ClassReader($file, $gClass); $compiler = new Compiler($classReader); return $compiler; }
public function testConstructInterfaceHierarchy() { return $this->assertTrue(true, 'einkommentieren zum compilieren'); $avaibleInterfaces = array('ComboDropBoxable', 'DropBoxButtonable', 'SelectComboBoxable', 'GridRowable', 'RightContentLinkable', 'Searchable', 'AutoCompletable', 'Patchable', 'NewButtonable', 'NewTabButtonable', 'DeleteButtonable', 'EditButtonable', 'TabButtonable', 'TabLinkable', 'TabOpenable', 'Buttonable', 'Deleteable', 'Identifyable'); $hierarchy = array(); foreach ($avaibleInterfaces as $avaibleInterface) { $hierarchy[$avaibleInterface] = array(); foreach (GClass::factory('Psc\\CMS\\Item\\' . $avaibleInterface)->getAllInterfaces() as $interface) { if ($interface->getNamespace() === '\\Psc\\CMS\\Item') { $hierarchy[$avaibleInterface][] = $interface->getFQN(); } } } $codeWriter = new \Psc\Code\Generate\CodeWriter(); $code = ' $avaibleInterfaces = Array(' . "\n"; foreach ($hierarchy as $trait => $interfaces) { $code .= sprintf(" '%s' => %s,\n", $trait, $codeWriter->exportList($interfaces)); } $code .= ' );' . "\n"; print "\n\n"; print $code; print "\n"; }
/** * Bestimmt ob für eine Klasse des Projektes ein Test erstellt werden soll, wenn diese automatisch erstellt wird * * z. B. Exceptions haben erstmal keinen Test */ public function shouldAutomaticTestCreated(GClass $class) { if (\Webforge\Common\String::endsWith($class->getName(), 'Exception')) { return FALSE; } /* more exceptions to come */ return TRUE; }
public function removeUsedClass(GClass $class) { if (array_key_exists($fqn = $class->getFQN(), $this->usedClasses)) { unset($this->usedClasses[$fqn]); } return $this; }
public static function missingController(GClass $controllerClass, $exception) { return new static(sprintf("Controller der Klasse: '%s' nicht gefunden. " . $exception->getMessage(), $controllerClass->getFQN())); }
public function testProperty() { $class = new ReflectionClass(__NAMESPACE__ . '\\TestClass'); $gClass = GClass::reflectorFactory($class); $prop1 = GProperty::reflectorFactory($class->getProperty('prop1'), $gClass); $this->assertEquals(TRUE, $prop1->hasDefaultValue(), 'hasDefaultValue'); $this->assertEquals('prop1', $prop1->getName()); $this->assertEquals('banane', $prop1->getDefaultValue()); $this->assertEquals(TRUE, $prop1->isProtected()); $this->assertEquals("protected \$prop1 = 'banane'", $prop1->php()); $prop2 = GProperty::reflectorFactory($class->getProperty('prop2'), $gClass); //$this->assertEquals(FALSE, $prop2->hasDefaultValue(), 'hasDefaultValue'); // php bug? hier gibt reflection TRUE als isDefault aus $this->assertEquals('prop2', $prop2->getName()); $this->assertEquals(FALSE, $prop2->isProtected()); $this->assertEquals(TRUE, $prop2->isPublic()); $this->assertEquals(TRUE, $prop2->isStatic()); $this->assertEquals("public static \$prop2", $prop2->php()); }
/** * @return bool */ protected function isInstanceOf(GClass $controllerClass, $fqn) { return $controllerClass->getReflection()->isSubclassOf($fqn); }
public function testOwnMethodForAbstractClassImplementingAnInterface() { $gClass = GClass::factory(__NAMESPACE__ . '\\MyAbstractInterfacedClass'); $this->assertFalse($gClass->hasOwnMethod('interfaceMethod1')); $this->assertTrue($gClass->hasMethod('interfaceMethod1')); }
use Psc\System\System; use Psc\Code\Generate\ClassWriter; use Webforge\Common\JS\JSONConverter; use Psc\JS\jQuery; use Seld\JsonLint\JsonParser; /** * * $createCommand = function ($name, array|closure $configure, closure $execute) { * * $arg = function ($name, $description = NULL, $required = TRUE) // default: required * $opt = function($name, $short = NULL, $withValue = TRUE, $description = NULL) // default: mit value required * $flag = function($name, $short = NULL, $description) // ohne value */ $createCommand('compile:komodo-command-call', array($arg('extension-name')), function ($input, $output, $command) { $extensionClass = Code::expandNamespace(\Webforge\Common\String::expand($input->getArgument('extension-name'), 'Extension'), 'Psc\\Code\\Compile'); $extension = GClass::factory($extensionClass); $fields = array(); if ($extension->hasMethod('__construct')) { foreach ($extension->getMethod('__construct')->getParameters() as $param) { $fields[] = $param->getName(); } } // das nimmt vielleicht zu viele, weis nicht, alternativ würds auch ne statische methode zur extension tun foreach ($extension->getProperties() as $property) { $fields[] = $property->getName(); } $json = array(); foreach (array_unique($fields) as $field) { $json[$field] = '%(ask:' . $field . ')'; } $command->comment(sprintf('Komodo-Command für %s:', $extension->getClassName()));
public function testWithGClass() { $gClass = new GClass('\\ePaper42\\Entities\\Journal'); $gClass->setParentClass(new GClass('\\Psc\\XML\\Object')); $gClass->createProperty('title')->createDocBlock("Titel des Objektes (Name der Zeitschrift)\n")->addSimpleAnnotation('xml:XmlElement'); $gClass->createProperty('key')->createDocBlock("Key des Objektes\n")->addSimpleAnnotation('xml:XmlElement'); $gClass->createProperty('volumes')->createDocBlock("Volumes des Journals (Jahreszahlen)\n")->addSimpleAnnotation('xml:XmlElement', array('name' => 'volumne', 'wrapper' => 'volumeList', 'type' => 'ePaper42\\Entities\\Volume')); $classCode = <<<'CLASS_END' class Journal extends \Psc\XML\Object { /** * Titel des Objektes (Name der Zeitschrift) * * @xml:XmlElement */ protected $title; /** * Key des Objektes * * @xml:XmlElement */ protected $key; /** * Volumes des Journals (Jahreszahlen) * * @xml:XmlElement(name="volumne", wrapper="volumeList", type="ePaper42\Entities\Volume") */ protected $volumes; } CLASS_END; //file_put_contents('D:\fixture.txt',$classCode); //file_put_contents('D:\actual.txt',$gClass->php()); $this->assertEquals($classCode, $gClass->php()); }
/** * Erstellt ein leeres Entity * * kann abgeleitet werden, falls der constructor von {$this->getEntityName()} Parameter braucht */ public function createEmptyEntity($revision = NULL) { // @TODO check ob entity einen constructor hat, der parameter braucht? $c = $this->getEntityName(); try { $gClass = new GClass($c); // wir rufen hier nicht den constructor auf return $gClass->newInstance(array(), GClass::WITHOUT_CONSTRUCTOR); } catch (\ErrorException $e) { if (mb_strpos($e->getMessage(), 'Missing argument') !== FALSE) { throw new \Psc\Exception(sprintf("Kann kein leeres Entity '%s' mit leerem Constructor erstellen. createEmptyEntity() kann im Controller abgeleitet werden, um das Problem zu beheben", $c), 0, $e); } else { throw $e; } } }
public function inferFile(GClass $class) { if ($class->getNamespace() === $this->module->getEntitiesNamespace()) { $file = $this->module->getEntitiesPath()->getFile($class->getClassName() . '.php'); } else { $file = Code::mapClassToFile($class->getFQN(), $this->module->getProject()->dir('lib')); } return $file; }
protected function parseExtensionGClass($input) { $extensionClass = Code::expandNamespace(\Webforge\Common\String::expand($input->getArgument('name'), 'Extension'), 'Psc\\Code\\Compile'); return GClass::factory($extensionClass); }
/** * Fügt dem Writer für die aktuelle Klasse einen weiteren Import hinzu * * dies wird bei setClass() jedoch verworfen, also nach setClass aufrufen * wird kein Alias gesetzt wird der Klassename als Alias benutzt (dies entspricht dem Verhalten von PHP) */ public function addImport(GClass $import, $alias = NULL) { $explicit = TRUE; if ($alias === NULL) { $explicit = FALSE; $alias = $import->getClassName(); } if (array_key_exists($alias, $this->foundImports) && !$this->foundImports[$alias]->equals($import)) { throw new Exception(sprintf("Alias: '%s' wurde doppelt requested von: '%s' (%s) und '%s' ", $alias, $import->getFQN(), $explicit ? 'explizit' : 'implizit', $this->foundImports[$alias]->getFQN())); } $this->foundImports[$alias] = $import; return $this; }
/** * Entfernt die Default Value aus der Klasse * * dies ist nicht dasselbe wie $this->setDefaultValue(NULL) ! */ public function removeDefaultValue() { $this->gClass->removeDefaultValue($this); return $this; }