blog.humaneguitarist.org

making a DOT graph for PHP include statements

[Sat, 30 Jul 2011 17:03:02 +0000]
A couple of months ago, I posted [http://blog.humaneguitarist.org/2011/05/07/making-my-first-dependency-graph/] about my experience with making a Python dependency graph. Of course, as the post states, I was originally looking for a way to make a graph showing the relationship among PHP files in regard to "include" statements. Well, I'm home sick and after a few hours of trying to find an easy, out-of-box solution I gave up and rolled my own Python script to make me a DOT [http://en.wikipedia.org/wiki/DOT_language] graph file. I didn't have anything better to do. :( The results are pretty simplistic, but I'm happy enough with it for now. The Python script takes three arguments: the directory in which the PHP files exist, whether to search recursively or not (0=no, 1=yes), and the name of the output file as such: $ python makeDOT.py blog/wordpress 1 wordpressIncludes.dot<br/> ##### #importing modules import glob, re, sys, os, fnmatch br = "\n" tab = "\t" ##### #exiting if all 3 arguments are not passed via command line def fail(): print ("ERROR: " + str(len(sys.argv)-1) + " of 3 required arguments provided.") sys.exit() ##### #getting arguments passed via command line #testing for root DIRECTORY string try: myDir = sys.argv[1] except: fail() #testing for RECURSION boolean try: myRec = sys.argv[2] except: fail() #testing for OUTPUT filename string try: myFile = sys.argv[3] except: fail() ##### #making list of PHP files within DIRECTORY if myRec == "0": #without recursion myDir2 = myDir + "/*.php" PHP_list = glob.glob(myDir2) elif myRec == "1": #with recursion PHP_list = [] for dirname, dirnames, filenames in os.walk(myDir): for filename in filenames: if fnmatch.fnmatch (filename,("*.php")): match = os.path.join(dirname,filename) PHP_list.append(match) #make an empty list; #tuples will go in the list; #each tuple will contain a PHP filename and a PHP filename it includes includeList = [] #iterate through each PHP file and place tuples in the list for phpFile in PHP_list: fileOpen = open(phpFile, "r") #for each line in a PHP file for line in fileOpen: m = re.match(r"(.*)include(.*\()(.*)\)", line) #for include(),include_once() if m: matchFile = m.group(3)[1:-1] if matchFile[-4::] == ".php": #only PHP files phpFile = phpFile.replace("\\","/") matchFile = matchFile.replace("\\","/") matchFile = matchFile.replace("\"","") matchFile = matchFile.replace('\'',"") includeList.append([phpFile[len(myDir)+1:], matchFile]) else: pass m = re.match(r'(.*)require(.*\()(.*)\)', line) #for require(), require_once() if m: matchFile = m.group(3)[1:-1] if matchFile[-4::] == '.php': #only PHP files phpFile = phpFile.replace("\\","/") matchFile = matchFile.replace("\\","/") matchFile = matchFile.replace("\"","") matchFile = matchFile.replace('\'',"") includeList.append([phpFile[len(myDir)+1:], matchFile]) else: pass ##### #creating DOT file dot = open(myFile, "w") #writing to DOT file dot.write("digraph {" + br) for a,b in includeList: dot.write(tab) dot.write("\"") dot.write(a) dot.write("\"") dot.write(" -> ") dot.write("\"") dot.write(b) dot.write("\"") dot.write(";") dot.write(br) dot.write("}") dot.close() ##### #exiting sys.exit() I ran the Python script on the PHP scripts for MXMLiszt [http://blog.humaneguitarist.org/projects/mxmliszt/]. Then I used the "circo" layout engine in Graphviz [http://en.wikipedia.org/wiki/Graphviz] - specifically the Gvedit.exe application - on this [http://blog.humaneguitarist.org/uploads/MXMLisztIncludeGraph.dot.txt] resultant DOT file. Here's the result: IMAGE: [http://blog.humaneguitarist.org/uploads/MXMLisztIncludeGraph.gif]

COMMENTS

  1. nitin [2013-09-13 16:54:27]

    Hey, This looks really cool! Thanks for letting me know.

  2. Nick [2013-09-13 16:49:52]

    I was inspired by your post here and I was delighted to see that you used Python. I used your code at first and it worked wonderfully. I went from there and wrote my own script to create a JSON file suitable for use with D3, since the layout algorithms and interactibility with graphviz left me wanting. I also wanted to be able to show the results to a wider audience than myself. Here's my code: https://github.com/tothebeat/phpgraph [https://github.com/tothebeat/phpgraph] I ran my script on the MediaWiki source code, and you can see the resulting D3 force-directed graph here: http://bl.ocks.org/tothebeat/6551304 Thanks for sharing your work!

  3. nitin [2012-09-26 11:19:39]

    Hey Carl, thanks for sharing this!

  4. carl [2012-09-24 17:33:41]

    Hi, nice script. I made some improvements, maybe you want to make an update? Editor's note: Due to indentation issues I've moved Carl's code to its own post here: http://blog.humaneguitarist.org/2013/06/23/an-improved-php-includes-to-dot-graph-script-by-carl/ [http://blog.humaneguitarist.org/2013/06/23/an-improved-php-includes-to-dot-graph-script-by-carl/]