Skip to content
Snippets Groups Projects
Commit b63f5679 authored by totten's avatar totten
Browse files

Add tpl-lint tool inspired by pull request #132

parent 247506c6
No related branches found
No related tags found
No related merge requests found
#!/usr/bin/env php
<?php
// FIXME: Make this a proper app with unit-tests
$civi_pkgs_dir = dirname( dirname( dirname( __FILE__ ) ) ) . DIRECTORY_SEPARATOR . 'packages';
require_once $civi_pkgs_dir . DIRECTORY_SEPARATOR . 'simple_html_dom.php';
exit(main($argv));
/**
* Scan a series of files for suspicious code
*
* example: find templates -name '*.tpl' | xargs php tools/scripts/tpl-lint
*
* @param array $argv
* @return int
*/
function main($argv) {
$files = $argv;
array_shift($files); // skip program name
foreach ($files as $file) {
check_tpl($file, function($code, $message) use ($file) {
printf("[%s] %s\n", $file, $message);
});
}
return 0;
}
/**
* Scan a file for suspicious code
*
* @param string $file
* @param callable $reporter
* @return void
*/
function check_tpl($file, $reporter) {
$html = file_get_html($file);
foreach ($html->find('a') as $a) {
check_a($a, $reporter);
}
}
/**
* Scan an <A> tag
*
* @param object $a
* @param callable $reporter
* @return void
*/
function check_a($a, $reporter) {
if (!$a->hasAttribute('href')) {
// anchor, don't care
return;
}
$href = trim($a->getAttribute('href'));
if (preg_match('/javascript:/', $href)) {
$reporter('javascript-url', "<a> has javascript url: $href");
return;
}
if ($href == '#' && $a->hasAttribute('onclick')) {
$onclick = $a->getAttribute('onclick');
if (!js_returns_false($onclick) && !js_returns_func($onclick)) {
$reporter('a-no-return', "<a> has href=# but handler fails to return false: $onclick");
return;
}
}
if ($href != '#' && $a->hasAttribute('onclick')) {
$onclick = $a->getAttribute('onclick');
$reporter('a-double-action', "<a> has both URL ($href) and onclick ($onclick)");
return;
}
}
/**
* Determine if snippet of JS returns strictly false
*/
function js_returns_false($js) {
return
// last in a series of statements
preg_match('/; *return +false *; *$/', $js)
||
// only statement
preg_match('/^ *return +false *;? *$/', $js);
}
/**
* Determine if snippet of JS returns a function call
*/
function js_returns_func($js) {
return preg_match('/^ *return +[a-zA-Z0-9\._$]+\(/', $js);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment