public function generateActionPath(\Symforce\AdminBundle\Compiler\Cache\ActionCache $action, \Symfony\Component\Routing\RouteCollection $route_admin_collection) { $class = $this->loader->getCompileClass(); $writer = $this->loader->getCompileAdminWriter(); $route_name = $action->getAdminRouteName(); $admin_name = $this->admin->getName(); $admin_class = $this->admin->getClassName(); $generator = new \Symforce\AdminBundle\Compiler\Generator\PhpWriter(); $dispatcher = new \Symforce\AdminBundle\Compiler\Generator\PhpWriter(); $requirement = array(); $generator->write('function(PropertyAccessorInterface $accessor, AdminLoader $loader, '); if ($action->isRequestObject()) { $generator->write(sprintf('%s $%s_object, ', '\\' . $admin_class, $admin_name)); } $generator->writeln('array $options = array()){')->indent(); $dispatcher->writeln('function(AdminLoader $loader, Request $request){')->indent(); $dispatcher->writeln(sprintf('$loader->setRouteAdminAction("%s", "%s");', $admin_name, $action->getName())); $dispatcher->writeln('$_sf_admin_route_parameters = array();'); $dispatcher->writeln('$_sf_admin_route_parents = array();'); $path = array(); $route_generator_parents = array(); $this->getRoutePatentGenerator($route_generator_parents); foreach ($route_generator_parents as $route_parent_generator) { $route_parent_generator->generateRouteDispatcher($dispatcher, $requirement, $path); } $dispatcher->writeln(sprintf('$%s = $loader->getAdminByClass("%s");', $admin_name, $admin_class)); $dispatcher->writeln(sprintf('$%s->setRouteParameters($_sf_admin_route_parameters);', $admin_name)); $dispatcher->writeln(sprintf('$%s->setRouteParents($_sf_admin_route_parents);', $admin_name)); $route_parent = $this->admin->getRouteParent(); if ($route_parent) { $admin_name = $this->admin->getName(); $dispatcher->writeln(sprintf('$%s->setRouteParent($%s);', $admin_name, $route_parent->getName())); $dispatcher->writeln(sprintf('$%s->setRouteParentProperty("%s");', $admin_name, $this->admin->getRouteParentProperty())); } if ($action->isRequestObject()) { $dispatcher->writeln(sprintf('$%s->setRouteObjectId( $request->get("%s_id") );', $admin_name, $admin_name)); } $dispatcher->writeln(sprintf('$action = $%s->getAction("%s");', $admin_name, $action->getName())); if ($action->isRequestObject()) { $generator->writeln(sprintf('$options["%s_id"] = $accessor->getValue($%s_object, "%s") ;', $admin_name, $admin_name, $this->admin->getPropertyIdName())); } $this->generateRouteGenerator($generator, $action->isRequestObject(), true); if ($route_parent) { $route_parent_renerator = $this->loader->getAdminRouteGenerator($route_parent->getName()); if (!$route_parent_renerator->isSingleChild($this->admin_name)) { $path[] = 'of_' . $this->admin->getRouteParentProperty(); } } $path[] = $admin_name; if ($this->admin->tree) { $id = 'sf_admin_tree_parent'; $requirement[$id] = '\\d+'; $generator->writeln(sprintf('if( !isset($options["%s"]) ) $options["%s"] = 0;', $id, $id)); $path[] = sprintf('{%s}', $id); $dispatcher->writeln(sprintf('$%s->setTreeObjectId( $request->get("%s") );', $admin_name, $id)); } if ($this->admin->workflow) { $id = 'admin_route_workflow'; $requirement[$id] = '\\w+'; $path[] = sprintf('{%s}', $id); $dispatcher->writeln(sprintf('$%s->setRouteWorkflow( $request->get("%s") );', $admin_name, $id)); $generator->writeln(sprintf('if( !isset($options["%s"]) ) $options["%s"] = $loader->getAdminByClass("%s")->getRouteWorkflow();', $id, $id, $admin_class)); } $owner = self::getPropertyValue($this->admin, 'property_owner_name'); if ($owner) { $id = 'admin_route_owner_identity'; $requirement[$id] = '\\w+'; $path[] = sprintf('{%s}', $id); $dispatcher->writeln(sprintf('$%s->setRouteOwnerIdentity( $request->get("%s") );', $admin_name, $id)); $generator->writeln(sprintf('if( !isset($options["%s"]) ) $options["%s"] = $loader->getAdminByClass("%s")->getRouteOwnerIdentity();', $id, $id, $admin_class)); $id = 'admin_route_owner_id'; $requirement[$id] = '\\d+'; $path[] = sprintf('{%s}', $id); $dispatcher->writeln(sprintf('$%s->setRouteOwnerId( $request->get("%s") );', $admin_name, $id)); $generator->writeln(sprintf('if( !isset($options["%s"]) ) $options["%s"] = $loader->getAdminByClass("%s")->getRouteOwnerId();', $id, $id, $admin_class)); } $path[] = $action->getName(); if ($action->isRequestObject()) { $path[] = sprintf('{%s_id}', $admin_name); } if ($action->isListAction()) { $id = 'admin_list_page'; $requirement[$id] = '\\d+'; $generator->writeln(sprintf('if( !isset($options["%s"]) ) $options["%s"] = 1;', $id, $id)); $path[] = sprintf('{%s}.html', $id); $dispatcher->writeln(sprintf('$action->setPageNumber( $request->get("%s") );', $id)); } $path = '/' . join('/', $path); $route_config = array('_controller' => 'Symforce\\AdminBundle\\Controller\\AdminController::adminAction', '_sf_route_name' => $route_name); $route = new \Symfony\Component\Routing\Route($path, $route_config, $requirement); $route_admin_collection->add($route_name, $route); $dispatcher->writeln('return $action;'); $generator->writeln(sprintf('// path = %s ', $path)); $generator->writeln('return $options;'); $writer->write(sprintf('$this->admin["%s"]["generator"] = ', $route_name))->indent()->write($generator->getContent())->outdent()->writeln("};"); $writer->write(sprintf('$this->admin["%s"]["dispatcher"] = ', $route_name))->indent()->write($dispatcher->getContent())->outdent()->writeln('};'); }
public function addRoute(\ReflectionMethod $m, \Symforce\AdminBundle\Compiler\Annotation\Route $annot, array $as = null) { $this->err_msg = sprintf("%s->%s(@%s): ", $m->getDeclaringClass()->getName(), $m->getName(), self::ROUTE_ANNOT_CLASS); $admin_name = null; if ($annot->admin) { if (!preg_match('/^\\w+$/', $annot->admin)) { throw new \Exception(sprintf("%s admin `%s` invalid ", $this->err_msg, $annot->admin)); } $admin_name = $annot->admin; } else { $admin_name = $this->page_loader->getControlerOwnerName($m); } $action_name = null; if ($annot->action) { if (!preg_match('/^\\w+$/', $annot->action)) { throw new \Exception(sprintf("%s admin `%s` invalid ", $this->err_msg, $annot->action)); } $action_name = $annot->action; } else { $action_name = $annot->action ?: strtolower(preg_replace('/Action$/', '', $m->getName())); } if ($admin_name !== $this->admin_name) { $this->page_loader->addOtherControlerAction($admin_name, $action_name, $m); return; } $this->page_loader->addPageAction($admin_name, $action_name, $m); $controller_name = basename(str_replace('\\', '/', $m->getDeclaringClass()->getName())); if (!$annot->name) { $annot->name = $admin_name . '.' . $action_name; } if ($annot->alias) { if (!preg_match('/^(.+?)\\s*\\:\\s*(.+)$/', $annot->alias, $ms)) { throw new \Exception(sprintf("%s alias `%s` invalid ", $this->err_msg, $annot->alias)); } $admin_alias = $ms[1]; $action_alias = $ms[2]; if (!$this->loader->hasAdminName($admin_alias)) { throw new \Exception(sprintf("%s admin name `%s` not exists in alias `%s`", $this->err_msg, $admin_alias, $annot->alias)); } $page_generator_alias = $this->page_loader->getPageGeneratorByName($admin_alias); $page_generator_alias->addAlias($action_alias, $admin_name, $action_name, $m); } if (!$annot->template) { $annot->template = $this->admin->getBundleName() . ':' . preg_replace('/Controller$/', '', $controller_name) . ':' . $admin_name . '.' . $action_name . '.html.twig'; } $requirement_keys = array(); if (!$annot->path) { if ('index' === $action_name && !$annot->entity) { $annot->path = '/' . $this->route_path . '/'; } else { if ('view' === $action_name && null === $annot->entity) { $annot->entity = true; } if ($annot->entity) { $annot->path = '/' . $this->route_path . '/' . $action_name . '/{' . $this->eneity_id_name . '}'; $requirement_keys[$this->eneity_id_name] = true; } else { $annot->path = '/' . $this->route_path . '/' . $action_name . '/'; } } } else { $annot->path = '/' . ltrim($annot->path, '/'); if (preg_match_all('/\\{(.+?)\\}/', $annot->path, $ms)) { foreach ($ms[1] as $requirement_key) { if (isset($requirement_keys[$requirement_key])) { throw new \Exception(sprintf("%s : `%s` duplicate in path `%s`", $this->err_msg, $annot->path, $requirement_key)); } $requirement_keys[$requirement_key] = true; } } if (isset($requirement_keys['entity_id'])) { $annot->path = str_replace('{entity_id}', '{' . $this->eneity_id_name . '}', $annot->path); $annot->entity = true; $requirement_keys[$this->eneity_id_name] = true; unset($requirement_keys['entity_id']); } if (isset($requirement_keys[$this->eneity_id_name])) { $annot->entity = true; } } $generator = new \Symforce\AdminBundle\Compiler\Generator\PhpWriter(); $dispatcher = new \Symforce\AdminBundle\Compiler\Generator\PhpWriter(); $dispatcher_args = array(); $entity_object_name = '$' . $this->admin_name; $generator->write('function(\\Symfony\\Component\\PropertyAccess\\PropertyAccessorInterface $accessor,'); if ($annot->entity) { $generator->write(sprintf('%s %s, ', '\\' . $this->admin_class, $entity_object_name)); } else { if ($this->page_parent_entity) { $entity_object_name = '$' . $this->parent_admin->getName(); $generator->write(sprintf('%s %s, ', '\\' . $this->parent_admin->getClassName(), $entity_object_name)); } } $generator->writeln('array $options = array() ){')->indent(); $dispatcher->writeln('function(\\Symfony\\Component\\PropertyAccess\\PropertyAccessorInterface $accessor, \\' . $m->getDeclaringClass()->getName() . ' $controller, \\Symfony\\Component\\HttpFoundation\\Request $request){')->indent(); $dispatcher->writeln(sprintf('$controller->setPageAdmin("%s");', $this->admin_name)); $requirements = array(); $requirements_entitys = array(); $route_config = array('_controller' => $m->getDeclaringClass()->getName() . '::dispatchAction', '_sf_web_page' => $admin_name . ':' . $action_name); $path = $this->getRoutePath($requirements_entitys, $requirements, $requirement_keys, $generator, $dispatcher, $annot->entity, $annot->path); $defaults = array(); if ($annot->defaults) { $defaults = $annot->defaults; } foreach ($requirements_entitys as $requirement_key) { if (isset($requirement_keys[$requirement_key])) { unset($requirement_keys[$requirement_key]); } } if ($annot->requirements) { foreach ($annot->requirements as $requirement_key => $value) { if (isset($requirements[$requirement_key])) { throw new \Exception(sprintf("%s `%s` duplicate requirements:%s ", $this->err_msg, $path, $requirement_key)); } $requirements[$requirement_key] = $value; } } $add_default = function ($i, $name, $value) use(&$dispatcher_args, $generator) { $dispatcher_args[$i] = sprintf('$request->get("%s", %s)', $name, var_export($value, 1)); $generator->writeln(sprintf(' if( !isset($options["%s"]) ) $options["%s"] = %s;', $name, $name, var_export($value, 1))); }; foreach ($m->getParameters() as $i => $p) { $requirement_key = $p->getName(); if (isset($requirement_keys[$requirement_key])) { if (isset($defaults[$requirement_key])) { $add_default($i, $requirement_key, $defaults[$requirement_key]); unset($defaults[$requirement_key]); } else { if ($p->isDefaultValueAvailable()) { $add_default($i, $requirement_key, $p->getDefaultValue()); } else { $dispatcher_args[$i] = sprintf('$request->get("%s")', $p->getName()); } } unset($requirement_keys[$requirement_key]); } else { if (!$p->isDefaultValueAvailable()) { // check if is request if ($p->getClass()) { $requirement_class = $p->getClass()->name; if ('Symfony\\Component\\HttpFoundation\\Request' === $requirement_class) { $dispatcher_args[$i] = '$request'; } else { if (isset($requirements_entitys[$requirement_class])) { $dispatcher_args[$i] = '$' . $this->loader->getNameByClass($requirement_class); } else { if ($this->loader->hasSuperAdminClass($requirement_class)) { $super_class = $this->loader->getSuperAdminClass($requirement_class); $dispatcher_args[$i] = '$controller->getAdminByClass(' . var_export($super_class, 1) . ')'; } else { throw new \Exception(sprintf("%s parameter:(%s %s) not defined on path:%s", $this->err_msg, $requirement_class, $requirement_key, $annot->path)); } } } } else { if (isset($defaults[$requirement_key])) { $add_default($i, $requirement_key, $defaults[$requirement_key]); unset($defaults[$requirement_key]); } else { throw new \Exception(sprintf("`%s` no value", $requirement_key)); } } } else { // maybe need add to other place $dispatcher_args[$i] = var_export($p->getDefaultValue(), 1); } } } if (!empty($defaults)) { throw new \Exception(sprintf("%s defaults:%s not defined on path:%s", $this->err_msg, json_encode($defaults), $annot->path)); } if (!empty($requirement_keys)) { throw new \Exception(sprintf("%s path option `{%s}` not defined on path:%s", $this->err_msg, json_encode($requirement_keys), $annot->path)); } $this->action_cache[$action_name] = $annot; $route = new \Symfony\Component\Routing\Route($path, $route_config, $requirements); $this->page_loader->addPageRoute($admin_name, $action_name, $route, $m, $annot); $page_class = $this->page_loader->getCompileClass(); $writer = $page_class->getLazyWriter(); $generator->writeln('return $options;'); $dispatcher->writeln(sprintf('return $controller->%s(%s);', $m->getName(), join(', ', $dispatcher_args))); $writer->write(sprintf('$this->cache["%s:%s"]["generator"] = ', $admin_name, $action_name))->indent()->write($generator->getContent())->writeln('}')->outdent()->writeln(";"); $writer->write(sprintf('$this->cache["%s:%s"]["dispatcher"] = ', $admin_name, $action_name))->indent()->write($dispatcher->getContent())->writeln('}')->outdent()->writeln(";"); return true; }