Im writing a plugin library, and part of the plugin installation is to check the plugins .php files and look at all class/methods/functions it uses, and just display a notice if whats utilized in the plugin.
The part im not 100% sure on, is how should I profile the classes/methods/functions? Right now, I have a file that contains an array, which has a friendly name of the class, then the regex pattern to use when searching for it, and a description.
class_profiles.php
PHP Code:
<?php
$classes = array(
'CI Framework' => array(
'class' => 'CI_*',
'regex' => 'CI_(.*)',
'description' => 'CodeIgniter Framework - Any classes used by the CodeIgniter framework'
),
'Custom Codeigniter' => array(
'class' => 'MY_*',
'regex' => 'MY_(.*)',
'description' => 'Custom CI Classes - Classes used to customize some CodeIgniter classes'
),
'Account Controller' => array(
'class' => 'Account',
'regex' => 'Account',
'description' => 'Accounts Controller - Used to facilitate account related functionality (login, logout, etc)'
),
'Admin Controller' => array(
'class' => 'Admin',
'regex' => 'Admin',
'description' => 'Admin Controller - Used to facilitate administrative functionality'
)
);
Currently, heres a rough draft of the function that parses the plugins php files, (Its not done, just including it to give you an idea of what its doing thus far)
PHP Code:
<?php
public function get_class_usages($plugin)
{
// Get the base path of the plugin
$plugin_path = "/{$this->plugin_path}/{$plugin}/";
// Should get re-defined once class_profiles.php loads
$classes = NULL;
// An array of class names and their data
require_once APPPATH . 'libraries/class_profiles.php';
//die('CLASSES:<pre>' . print_r($classes, TRUE));
$files = array();
if( ! $dir = @new RecursiveDirectoryIterator( realpath($plugin_path) ))
{
Logger_lib::error("Failed to read from plugin path: {$plugin_path}", TRUE, TRUE);
return FALSE;
}
$objects = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::SELF_FIRST);
foreach($objects as $name => $object)
{
if(preg_match('/\.php$/', $name))
{
array_push($files, $name);
}
}
$matches = array();
foreach($files as $f)
{
$line_num = 0;
if( ! $fh = @fopen($f, 'r'))
{
Logger_lib::error("Failed to open plugin file for parsing: {$f}", TRUE, TRUE);
return FALSE;
}
$file_lines = array();
while ( ! feof($fh))
{
$line_num++;
$line = fgets($fh, 4096);
$file_lines[] = trim($line);
// @todo Add a few lines before and after the match to a preview of the line
foreach($classes as $c => $d) // Classes is defined in class_profiles.php
{
if (preg_match('/' . $d['regex'] . '/', $line)) {
$matches[$c][] = array(
'file' => $f,
'class' => $d['class'],
'line_num' => $line_num,
'line' => trim($line)
);
}
}
}
fclose($fh);
}
return $matches;
}
So, does anyone think that there might be a better way to do this? I was thinking maybe look for the PHPDoc comments of the functions/classes as the description? That might just be used to populate the class_profiles.php though.
Also, if theres a function "something", How would one ensure that the regex is matching the class, and not just something in a sentence.