protected function processClass(ReflectionClass $classRefl, Annotation $desc) { $class = $classRefl->getName(); $namespace = $desc->get("namespace"); $controllerName = "{$namespace}/" . $classRefl->getShortName(); $deps = $this->annotationReader->getClassAnnotation($classRefl, "Agit\\ApiBundle\\Annotation\\Depends") ?: new Depends(); $this->checkConstructor($classRefl, $deps); if (!$namespace) { throw new InternalErrorException(sprintf("ATTENTION: missing namespace on %s\n", $class)); } if ($desc instanceof EntityController) { $this->processEntityController($desc, $classRefl, $controllerName, $deps); } foreach ($classRefl->getMethods() as $methodRefl) { $annotationList = $this->annotationReader->getMethodAnnotations($methodRefl); $endpointMeta = []; foreach ($annotationList as $annotation) { if ($annotation instanceof AbstractEndpointMeta) { $endpointMetaName = StringHelper::getBareClassName($annotation); $endpointMeta[$endpointMetaName] = $annotation; } } if (!isset($endpointMeta["Endpoint"]) || !isset($endpointMeta["Security"])) { continue; } if (!$methodRefl->isPublic()) { throw new InternalErrorException(sprintf("ATTENTION: %s->%s must be public!\n", $class, $methodRefl->getName())); } // fix implicit namespaces in request and response $endpointMeta["Endpoint"]->set("request", $this->fixObjectName($namespace, $endpointMeta["Endpoint"]->get("request"))); $endpointMeta["Endpoint"]->set("response", $this->fixObjectName($namespace, $endpointMeta["Endpoint"]->get("response"))); $endpoint = sprintf("%s.%s", $controllerName, $methodRefl->getName()); $this->addEntry($endpoint, ["class" => $class, "deps" => $this->dissectMeta($deps), "method" => $methodRefl->getName(), "meta" => $this->dissectMetaList($endpointMeta)]); } }
protected function processClass(ReflectionClass $classRefl, Annotation $desc) { $class = $classRefl->getName(); $namespace = $desc->get("namespace"); $allDefaults = $classRefl->getDefaultProperties(); $defaults = []; if ($desc->get("objectName") !== null) { throw new InternalErrorException("Error in Object annotation on {$class}: You must not set the `objectName` parameter, it will be set automatically."); } if (!$namespace) { throw new InternalErrorException(sprintf("ATTENTION: missing namespace on %s\n", $class)); } $objectName = "{$namespace}/" . $classRefl->getShortName(); $objectMeta = []; $propMetaList = []; $desc->set("objectName", $objectName); $objectMeta["Object"] = $desc; $deps = $this->annotationReader->getClassAnnotation($classRefl, "Agit\\ApiBundle\\Annotation\\Depends") ?: new Depends(); foreach ($classRefl->getProperties() as $propertyRefl) { $annotations = $this->annotationReader->getPropertyAnnotations($propertyRefl); $propName = $propertyRefl->getName(); $propMeta = []; foreach ($annotations as $annotation) { if (!$annotation instanceof AbstractPropertyMeta) { continue; } $propMetaClass = StringHelper::getBareClassName($annotation); $propMetaName = $annotation instanceof AbstractType ? "Type" : $propMetaClass; $propMeta[$propMetaName] = $annotation; } if (!isset($propMeta["Type"])) { continue; } $defaults[$propName] = $allDefaults[$propName]; if ($propMeta["Type"]->isListType() && !is_array($defaults[$propName])) { $defaults[$propName] = []; } if ($propMeta["Type"] instanceof ObjectType) { $targetClass = $propMeta["Type"]->get("class"); if (is_null($targetClass)) { throw new InternalErrorException("Error in {$objectName}, property {$propName}: The target class must be specified."); } $propMeta["Type"]->set("class", $this->fixObjectName($namespace, $targetClass)); } if (!isset($propMeta["Name"]) || !$propMeta["Name"]->get("value")) { $propMeta["Name"] = new Name(["value" => $propName]); } $propMetaList[$propName] = $this->dissectMetaList($propMeta); } // check scalar "objects" if ($objectMeta["Object"]->get("scalar") && (count($propMetaList) !== 1 || !isset($propMetaList["_"]))) { throw new InternalErrorException("Scalar objects must contain only a `_` property."); } $this->addEntry($objectName, ["class" => $classRefl->getName(), "deps" => $this->dissectMeta($deps), "objectMeta" => $this->dissectMetaList($objectMeta), "defaults" => $defaults, "propMetaList" => $propMetaList]); }
protected function execute(InputInterface $input, OutputInterface $output) { if (!$this->flock(__FILE__)) { return; } $bundleName = "Foo\\BarBundle"; if ($input->getArgument("bundle")) { $bundle = $this->getContainer()->get("kernel")->getBundle($input->getArgument("bundle")); $bundleName = $bundle->getNamespace(); } $apiNs = $input->getArgument("namespace") ? $input->getArgument("namespace") : "stuff.v1"; $em = $this->getContainer()->get("doctrine.orm.entity_manager"); $metadata = $em->getClassMetadata($input->getArgument("entity")); $className = StringHelper::getBareClassName($metadata->name); $assoc = $metadata->getAssociationNames(); $allFields = array_merge($assoc, $metadata->getFieldNames()); $tpl = []; foreach ($allFields as $prop) { $attr = ""; if (!in_array($prop, $assoc)) { $type = $metadata->getTypeOfField($prop); if ($type === "smallint" || $type === "integer" || $type === "decimal") { $attr = "@Property\\NumberType(minValue=, maxValue=)"; } elseif ($type === "text" || $type === "string") { $attr = "@Property\\StringType(minLength=, maxLength=)"; } elseif ($type === "boolean") { $attr = "@Property\\BooleanType"; } } else { $mapping = $metadata->getAssociationMapping($prop); $targetEntity = StringHelper::getBareClassName($mapping["targetEntity"]); $isOwning = $mapping["isOwningSide"]; if ($mapping["type"] & ClassMetadataInfo::TO_ONE && !$mapping["inversedBy"]) { $attr = "@Property\\ObjectType(class=\"{$targetEntity}\")"; } elseif ($mapping["type"] & ClassMetadataInfo::TO_MANY) { $attr = "@Property\\ObjectListType(class=\"{$targetEntity}\", minLength=, maxLength=)"; } } if ($attr) { $tpl[] = " /**\n" . " * @Property\\Name(\"{$prop}\")\n" . " * {$attr}\n" . " */\n" . " public \${$prop};\n"; } } $classTpl = sprintf("<?php\n\n" . "namespace {$bundleName}\\Api\\Object;\n\n" . "use Agit\\ApiBundle\\Annotation\\Object;\n" . "use Agit\\ApiBundle\\Annotation\\Property;\n" . "use Agit\\ApiBundle\\Api\\Object\\AbstractEntityObject;\n\n" . "/**\n" . " * @Object\\Object(namespace=\"{$apiNs}\")\n" . " */\n" . "class {$className} extends AbstractEntityObject\n" . "{\n%s}\n", implode("\n", $tpl)); $output->write($classTpl); }
protected function getEntityClassName($entity) { return is_callable([$entity, "getEntityClassName"]) ? $entity->getEntityClassName() : StringHelper::getBareClassName($entity); }