@@ -132,44 +132,65 @@ public function indexAction()
132132 */
133133 public function getNodeTypes () : array
134134 {
135- return [ClassMethod::class, Class_::class];
135+ return [Class_::class];
136136 }
137137 /**
138- * @param Class_|ClassMethod $node
138+ * @param Class_ $node
139139 */
140140 public function refactor (Node $ node ) : ?Node
141141 {
142- if ($ node instanceof Class_) {
143- return $ this ->addAbstractControllerParentClassIfMissing ($ node );
142+ if (!$ this ->annotationAnalyzer ->hasClassMethodWithTemplateAnnotation ($ node )) {
143+ return null ;
144+ }
145+ $ this ->decorateAbstractControllerParentClass ($ node );
146+ $ hasChanged = \false;
147+ $ classDoctrineAnnotationTagValueNode = $ this ->annotationAnalyzer ->getDoctrineAnnotationTagValueNode ($ node , SymfonyAnnotation::TEMPLATE );
148+ foreach ($ node ->getMethods () as $ classMethod ) {
149+ if (!$ classMethod ->isPublic ()) {
150+ continue ;
151+ }
152+ $ hasClassMethodChanged = $ this ->replaceTemplateAnnotation ($ classMethod , $ classDoctrineAnnotationTagValueNode );
153+ if ($ hasClassMethodChanged ) {
154+ $ hasChanged = \true;
155+ }
144156 }
145- return $ this ->replaceTemplateAnnotation ($ node );
157+ if (!$ hasChanged ) {
158+ return null ;
159+ }
160+ // cleanup Class_ @Template annotaion
161+ if ($ classDoctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) {
162+ $ this ->removeDoctrineAnnotationTagValueNode ($ node , $ classDoctrineAnnotationTagValueNode );
163+ }
164+ return $ node ;
146165 }
147- private function addAbstractControllerParentClassIfMissing (Class_ $ class ) : ? Class_
166+ private function decorateAbstractControllerParentClass (Class_ $ class ) : void
148167 {
149168 if ($ class ->extends instanceof Name) {
150- return null ;
151- }
152- if (!$ this ->annotationAnalyzer ->hasClassMethodWithTemplateAnnotation ($ class )) {
153- return null ;
169+ return ;
154170 }
171+ // this will make $this->render() method available
155172 $ class ->extends = new FullyQualified ('Symfony \\Bundle \\FrameworkBundle \\Controller \\AbstractController ' );
156- return $ class ;
157173 }
158- private function replaceTemplateAnnotation (ClassMethod $ classMethod ) : ? ClassMethod
174+ private function replaceTemplateAnnotation (ClassMethod $ classMethod, ? DoctrineAnnotationTagValueNode $ classDoctrineAnnotationTagValueNode ) : bool
159175 {
160176 if (!$ classMethod ->isPublic ()) {
161- return null ;
177+ return \false ;
162178 }
163179 $ doctrineAnnotationTagValueNode = $ this ->annotationAnalyzer ->getDoctrineAnnotationTagValueNode ($ classMethod , SymfonyAnnotation::TEMPLATE );
164- if (! $ doctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) {
165- return null ;
180+ if ($ doctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) {
181+ return $ this -> refactorClassMethod ( $ classMethod , $ doctrineAnnotationTagValueNode ) ;
166182 }
167- return $ this ->refactorClassMethod ($ classMethod , $ doctrineAnnotationTagValueNode );
183+ // global @Template access
184+ if ($ classDoctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) {
185+ return $ this ->refactorClassMethod ($ classMethod , $ classDoctrineAnnotationTagValueNode );
186+ }
187+ return \false;
168188 }
169- private function refactorClassMethod (ClassMethod $ classMethod , DoctrineAnnotationTagValueNode $ templateDoctrineAnnotationTagValueNode ) : ? ClassMethod
189+ private function refactorClassMethod (ClassMethod $ classMethod , DoctrineAnnotationTagValueNode $ templateDoctrineAnnotationTagValueNode ) : bool
170190 {
171191 $ hasThisRenderOrReturnsResponse = $ this ->hasLastReturnResponse ($ classMethod );
172- $ this ->traverseNodesWithCallable ($ classMethod , function (Node $ node ) use ($ templateDoctrineAnnotationTagValueNode , $ hasThisRenderOrReturnsResponse , $ classMethod ) : ?int {
192+ $ hasChanged = \false;
193+ $ this ->traverseNodesWithCallable ($ classMethod , function (Node $ node ) use ($ templateDoctrineAnnotationTagValueNode , $ hasThisRenderOrReturnsResponse , $ classMethod , &$ hasChanged ) : ?int {
173194 // keep as similar type
174195 if ($ node instanceof Closure || $ node instanceof Function_) {
175196 return NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN ;
@@ -178,14 +199,15 @@ private function refactorClassMethod(ClassMethod $classMethod, DoctrineAnnotatio
178199 return null ;
179200 }
180201 $ this ->refactorStmtsAwareNode ($ node , $ templateDoctrineAnnotationTagValueNode , $ hasThisRenderOrReturnsResponse , $ classMethod );
202+ $ hasChanged = \true;
181203 return null ;
182204 });
183205 if (!$ this ->emptyReturnNodeFinder ->hasNoOrEmptyReturns ($ classMethod )) {
184- return null ;
206+ return $ hasChanged ;
185207 }
186208 $ thisRenderMethodCall = $ this ->thisRenderFactory ->create (null , $ templateDoctrineAnnotationTagValueNode , $ classMethod );
187209 $ this ->refactorNoReturn ($ classMethod , $ thisRenderMethodCall , $ templateDoctrineAnnotationTagValueNode );
188- return $ classMethod ;
210+ return \true ;
189211 }
190212 private function hasLastReturnResponse (ClassMethod $ classMethod ) : bool
191213 {
@@ -242,11 +264,14 @@ private function refactorReturnWithValue(Return_ $return, bool $hasThisRenderOrR
242264 $ this ->removeDoctrineAnnotationTagValueNode ($ classMethod , $ doctrineAnnotationTagValueNode );
243265 $ this ->returnTypeDeclarationUpdater ->updateClassMethod ($ classMethod , SymfonyClass::RESPONSE );
244266 }
245- private function removeDoctrineAnnotationTagValueNode (ClassMethod $ classMethod , DoctrineAnnotationTagValueNode $ doctrineAnnotationTagValueNode ) : void
267+ /**
268+ * @param \PhpParser\Node\Stmt\Class_|\PhpParser\Node\Stmt\ClassMethod $node
269+ */
270+ private function removeDoctrineAnnotationTagValueNode ($ node , DoctrineAnnotationTagValueNode $ doctrineAnnotationTagValueNode ) : void
246271 {
247- $ phpDocInfo = $ this ->phpDocInfoFactory ->createFromNodeOrEmpty ($ classMethod );
272+ $ phpDocInfo = $ this ->phpDocInfoFactory ->createFromNodeOrEmpty ($ node );
248273 $ this ->phpDocTagRemover ->removeTagValueFromNode ($ phpDocInfo , $ doctrineAnnotationTagValueNode );
249- $ this ->docBlockUpdater ->updateRefactoredNodeWithPhpDocInfo ($ classMethod );
274+ $ this ->docBlockUpdater ->updateRefactoredNodeWithPhpDocInfo ($ node );
250275 }
251276 private function refactorStmtsAwareNode (StmtsAwareInterface $ stmtsAware , DoctrineAnnotationTagValueNode $ templateDoctrineAnnotationTagValueNode , bool $ hasThisRenderOrReturnsResponse , ClassMethod $ classMethod ) : void
252277 {
0 commit comments