Extracting function declarations from a PHP file - php

I'm looking to create an on-site API reference for my framework and application.
Basically, say I have a class file model.class.php:
class Model extends Object {
... code here ...
// Separates results into pages.
// Returns Paginator object.
final public function paginate($perpage = 10) {
... more code here ...
}
}
and I want to be able to generate a reference that my developers can refer to quickly in order to know which functions are available to be called. They only need to see the comments directly above each function and the declaration line. Something like this (similar to a C++ header file):
// Separates results into pages.
// Returns Paginator object.
final public function paginate($perpage = 10);
I've done some research and this answer looked pretty good (using Reflection classes), however, I'm not sure how I can keep the comments in.
Any ideas?
I want to keep the current comment formatting. Myself and the people who are working on the code hate the verbosity associated with PHPDocumentor. Not to mention a comment-rewrite of the entire project would take years, so I want to preserve just the // comments in plaintext.

Why don't you just run PHPDocumenter on the code?
PHPDoc is identical to JavaDoc, and will retain all the parameters and comments in the docblock above the function.
EDIT: Since you don't want PHPDoc, I think it would probably be easiest to write a RegEx parser to do it, since Reflection won't provide you with any surrounding comments.
PHP code to get the comment:
if(preg_match("#//(.+)$#",$line,$match)>0)
{
echo "Comment is: ".$match[1];
}

this is what phpdoc is for. you comment your code a specific way, following certain rules, and when you're done you run your code through a parser. It outputs exactly what you're looking for.

Related

Surrounding text with a method call

I have a class that has two methods that are used often:self::foo() and self::bar().
I would like to surround text, mainly variables in other methods. I can do comments, if/else, try/catch, etc, but I can't with arbitrary method calls.
I don't even know if PHPStorm does this, honestly. Does anyone know how to do this?
UPDATE
I would like to take this:
function func() {
return $variable;
}
and make it this:
function func() {
return self::foo($variable);
}
or
function func() {
return this->bar($variable);
}
You can create and use Live Template that will do what you want (surround current selection with predefined template): separate template for each method call.
http://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Early+Access+Program -- the last section "Creating Surround Templates" is what you need in particular.
You can extract a function using WebStorm's refactoring tools.
Do do so, mark the code you want to have extracted and press Ctrl + Alt + M.
For more info, have a look at JetBrains' Website:
http://blog.jetbrains.com/webide/2011/05/extract-function-method-refactoring-for-php/
Edit: Thanks for the clarification. I am not aware of a refactoring tool that fulfills this particular need. However, if you have a lot of occurrences in one file, Search and Replace might be helpful.

How to test debug_backtrace results?

Summary
I have a class that uses debug_backtrace() for reporting where a method was called. The method may be called in third party code either directly or via some helper method that's in the same package as the class in question. In the latter case the method will report the line from the third party code and not from the helper class, thus the index at which the actual caller is in the results varies, so I'd like to include a test in my PHPUnit suite which would ensure that the correct index is found in each use case.
Is there a way I could automatically and reliably figure out the correct line in the test file that my method should return?
tl;dr, code plz
Here's some code to demonstrate. This is just the most bare bones example of the situation, please disregard that it doesn't really make sense. The actual use case is more complex and it's very much possible, likely even, that at some point in time I will mess something up and the traces end up giving wrong results. I'd like my tests to catch that.
Classes.php:
<?php
class Tracer
{
public function send()
{
$trace = debug_backtrace();
if ($trace[1]['class'] === 'Helper') {
$calledOnLine = $trace[2]['line'];
} else {
$calledOnLine = $trace[1]['line'];
}
return $calledOnLine;
}
}
class Helper
{
public static function send()
{
$Tracer = new Tracer;
return $tracer->send();
}
}
TracerTest.php:
<?php
class TracerTest extends PHPUnit_Framework_TestCase
{
public function testGetProperCallerInfo()
{
$Tracer = new Tracer;
$result1 = $Tracer->send(); // $TargetLine1
$result2 = Helper::send(); // $TargetLine2
$this->assertEquals($TargetLine1, $result1);
$this->assertEquals($TargetLine2, $result2);
}
}
Ideas
I could hardcode the line numbers into the test, and then update them each and every time something higher up in the test file changes. Even if I separate this particular test to its own file it's still going to break at some point, and besides it's such an ugly solution I wouldn't be able to look myself in the eye anymore.
Another method might be to tag the target lines with comments, load the test file to an array with file() and find the tags in the array. This is still somewhat fragile, and not really all that elegant.
Ask yourself, what is the behavior you are trying to test?
If you want to ensure you are generating exact strings, then maybe test fixtures is a good idea.
Probably more easier to maintain is to assert parts of the string which can be easily inferred.
Alternatively, you can mock the function call itself with libraries such as
https://github.com/instaclick/ICBaseTestBundle/blob/master/Test/Helper/Unit/FunctionHelper.php
http://www.workhabit.com/labs/mock-function-testing-drupal
Since I haven't been able to find a better solution, I ended up putting together a small package that let's me find lines reliably from the test source.
Accepted answer is still up for grabs if you can come up with a better solution!
In case someone is interested, the package I made is here.

(Re)formatting PHP code in Vim

How do I format PHP code that looks like this
class SomeClass
{
function insideclass()
{
}
}
into this, using Vim without any external tool?
class SomeClass {
function insideclass() {
}
}
I am not arguing that this is the best way to format the code, but this is what we are following in the team.
Edit: Removed reference to the snippet addon, which caused some confusion about the question.
You have two unrelated problems and you won't find a unique solution to both.
You don't like the default class snippet.
No problem. If it's not already there, create ~/.vim/snippets/php.snippets and customize it to fit your team's rules by following the other answers. Snipmate is not smart enough to adapt itself to your coding style.
Some of your existing code doesn't conform to your coding rules.
Snipmate won't help at all since it only deals with insertion, not transformation. You are going to need either some external beautifier or a few macros.
EDIT
Here is a very simple command that does exactly what you want on your example. I offer no guarantee that it's going to work for everything everywhere. Take it as a naive starting point.
:g/^\s*{\s*$/normal kJ
:g/pattern acts on all lines containing pattern, see :h :global.
^\s*{\s*$ matches all single { whatever the amount of whitespace between them and the beginning of the line.
normal executes normal commands, see :h :normal.
kJ goes up one line and Joins this line with the matched line.
Done.
ENDEDIT
Why not modify the source code of that addon?
For example, change these:
snippet class
/**
* ${1}
*/
class ${2:ClassName}
{
${3}
function ${4:__construct}(${5:argument})
{
${6:// code...}
}
}
to
snippet class
/**
* ${1}
*/
class ${2:ClassName}{
${3}
function ${4:__construct}(${5:argument}){
${6:// code...}
}
}
Al the snipmate snippets are stored in a directory. Go to that directory and edit the file you want.
The direcorty is stored in the vim directory and called snippets. In there you see a php.snippets file. Go to that file and on line 70 you can edit the snippet for the class.

Hooking into function calls in php

A little background: At runtime I would like to be able to inspect the currently called functions javadoc-style documentation, to determine its formal (typed) declaration. This would allow runtime type checking (for simple and complex types) by means of reflection (at a cost) during debugging and testing, something that I would find immensely helpful.
So, in php I would like for a user defined function to get called whenever any other function is about to get called. That is, if a function foo() gets called, I would like to have my callHookHandler() function called immediately before.
One solution would be to implement __call() in all user defined classes, but that is both unwieldy and doesn't include support for functions defined outside classes, so I am looking for a better solution.
This sounds a bit of a fun one so I'm going to give answering it a try.
I hope this helps you. Let me know how it goes.
So, what you are asking can be done, and here's how:
For Functions:
Get all defined functions with $function = get_defined_functions().
Loop through the $functions['user'] key and inspect each one with the ReflectionFunction class. You'll need to get:
The comment using ->getDocComment()
The arguments using ->getParameters()
Do some magic (I'll let you figure out how to parse the comment using some regular extressions and match it up with the parameter list from the reflection. Don't forget optional parameters!)
Rename the function using runkit_function_rename
Generate code in a string that checks the parameters and calls the renamed function
Generate a parameter list as a string
Create a new function with runkit_function_add using the code you generated in step #5 and the parameter list from step #6.
For Classes:
Get a list of classes with $classes = get_declared_classes();
Loop through each one and inspect it with ReflectionObject and ->getMethods() to get the methods. Make sure that the class is not internal with ->isInternal() because we can't do anything about the internal classes.
In an inner loop... go through each method using the ReflectionMethod class. Get the arguments and PHPDoc/JavaDoc comments just like you did with normal functions.
Do the same thing you did with the functions only use runkit_method_add and runkit_method_rename instead.
Downsides:
You won't be able to do the checking on internal class methods and functions (which is fine because they won't have doc comments anyway).
This is a lot of work! I left a lot of parts up to your imagination to avoid this being the length of a short book.
Please send me this or open source it and let me know when you finish, I really want to use this myself. Contact info is on my website which is in my profile ;)
Alternatively:
You can use XDebug's function trace along with reflection then analyze the results after the fact so that you don't have to dynamically edit the code. If you want to write unit-test you could even automate it.
Hope type checking makes it into future versions of PHP and wait: https://wiki.php.net/rfc/typechecking
Notes:
This class reference has a potentially useful example of parsing docComments in the comments section of the page:
http://us.php.net/manual/en/class.reflectionmethod.php
References
get_defined_functions
get_declared_classes
ReflectionFunction
ReflectionObject
ReflectionMethod
runkit
Alternative way to hook into function call is to use a trick with namespaces: Intercepting Execution of System Functions in PHP
You can also use the Go! framework to define an aspect to intercept the execution of system functions automatically.

Create a PHP Class Outline

I am looking for a function or class that can effectively outline a class:
class MyClass{
/*
* Perhaps include the function comments
* in the function.
*/
function mainFunction(){
//Does Something
}
function functionWithArgs($arg1,$arg2=false){
//Does Something
//The function I want will give e the arguments w/default values
}
}
Is there a function or library in existence that can give me some kind of access to the information about this class, or even the file.
ex.
get_file_outline('fileWithAboveClass.php');
or
get_class_outline('MyClass');
Does anybody know of either, or know a way of easily writing this?
Take a look at the PHP Reflection API
//use the ReflectionClass to find out about MyClass
$classInfo = new ReflectionClass('MyClass');
//then you can find out pretty much anything you want to know...
$methods = $classInfo->getMethods();
var_dump($methods);
//you can even extract your comments, e.g.
$comment=$classInfo->getMethod('mainFunction')->getDocComment();
Note that for the comment extraction to work, they have to be formatted like PHPDoc / Doxygen comments, and begin with an opening /**
There's also a command line option available for inspecting functions and classes.
$ php --rc DateTime
will give you all the details about the DateTime-class, while
$ php --rf in_array
will give you the arguments of the "in_array" function.
If you're using the Terminal when coding it can be quite handy to use instead of looking it up in the PHP Manual all the time ;)

Categories