summaryrefslogtreecommitdiff
path: root/buildscripts/phing/classes/phing/tasks/ext/ZendCodeAnalyzerTask.php
blob: 490ee797e3e018f67653f3942f6df19c25d4944a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
<?php
require_once 'phing/Task.php';

/**
 * ZendCodeAnalyzerTask analyze PHP source code using the ZendCodeAnalyzer included in Zend Studio 5.1
 * 
 * Available warnings:
 * <b>zend-error</b> - %s(line %d): %s
 * <b>oneline-comment</b> - One-line comment ends with ?> tag.
 * <b>bool-assign</b> - Assignment seen where boolean expression is expected. Did you mean '==' instead of '='?
 * <b>bool-print</b> - Print statement used when boolean expression is expected.
 * <b>bool-array</b> - Array used when boolean expression is expected.
 * <b>bool-object</b> - Object used when boolean expression is expected.
 * <b>call-time-ref</b> - Call-time reference is deprecated. Define function as accepting parameter by reference instead.
 * <b>if-if-else</b> - In if-if-else construction else relates to the closest if. Use braces to make the code clearer.
 * <b>define-params</b> - define() requires two or three parameters.
 * <b>define-const</b> - First parameter for define() should be string. Maybe you forgot quotes?
 * <b>break-var</b> - Break/continue with variable is dangerous - break level can be out of scope.
 * <b>break-depth</b> - Break/continue with depth more than current nesting level.
 * <b>var-once</b> - Variable '%s' encountered only once. May be a typo?
 * <b>var-arg-unused</b> - Function argument '%s' is never used.
 * <b>var-global-unused</b> - Global variable '%s' is defined but never used.
 * <b>var-use-before-def</b> - Variable '%s' is used before it was assigned.
 * <b>var-use-before-def-global</b> - Global variable '%s' is used without being assigned. You are probably relying on register_globals feature of PHP. Note that this feature is off by default.
 * <b>var-no-global</b> - PHP global variable '%s' is used as local. Maybe you wanted to define '%s' as global?
 * <b>var-value-unused</b> - Value assigned to variable '%s' is never used
 * <b>var-ref-notmodified</b> - Function parameter '%s' is passed by reference but never modified. Consider passing by value.
 * <b>return-empty-val</b> - Function '%s' has both empty return and return with value.
 * <b>return-empty-used</b> - Function '%s' has empty return but return value is used.
 * <b>return-noref</b> - Function '%s' returns reference but the value is not assigned by reference. Maybe you meant '=&' instead of '='?
 * <b>return-end-used</b> - Control reaches the end of function '%s'(file %s, line %d) but return value is used.
 * <b>sprintf-miss-args</b> - Missing arguments for sprintf: format reqires %d arguments but %d are supplied.
 * <b>sprintf-extra-args</b> - Extra arguments for sprintf: format reqires %d arguments but %d are supplied.
 * <b>unreach-code</b> - Unreachable code in function '%s'.
 * <b>include-var</b> - include/require with user-accessible variable can be dangerous. Consider using constant instead.
 * <b>non-object</b> - Variable '%s' used as object, but has different type.
 * <b>bad-escape</b> - Bad escape sequence: \%c, did you mean \\%c?
 * <b>empty-cond</b> - Condition without a body
 * <b>expr-unused</b> - Expression result is never used
 *
 * @author   Knut Urdalen <knut.urdalen@telio.no>
 * @package  phing.tasks.ext
 */
class ZendCodeAnalyzerTask extends Task {
  
  protected $analyzerPath = ""; // Path to ZendCodeAnalyzer binary
  protected $file = "";  // the source file (from xml attribute)
  protected $filesets = array(); // all fileset objects assigned to this task
  protected $warnings = array();
  protected $counter = 0;
  protected $disable = array();
  protected $enable = array();
  
  /**
   * File to be analyzed
   * 
   * @param PhingFile $file
   */
  public function setFile(PhingFile $file) {
    $this->file = $file;
  }
  
  /**
   * Path to ZendCodeAnalyzer binary
   *
   * @param string $analyzerPath
   */
  public function setAnalyzerPath($analyzerPath) {
    $this->analyzerPath = $analyzerPath;
  }
  
  /**
   * Disable warning levels. Seperate warning levels with ','
   *
   * @param string $disable
   */
  public function setDisable($disable) {
    $this->disable = explode(",", $disable);
  }
  
  /**
   * Enable warning levels. Seperate warning levels with ','
   *
   * @param string $enable
   */
  public function setEnable($enable) {
    $this->enable = explode(",", $enable);
  }
  
  /**
   * Nested creator, creates a FileSet for this task
   *
   * @return FileSet The created fileset object
   */
  function createFileSet() {
    $num = array_push($this->filesets, new FileSet());
    return $this->filesets[$num-1];
  }

  /**
   * Analyze against PhingFile or a FileSet
   */
  public function main() {
    if(!isset($this->analyzerPath)) {
      throw new BuildException("Missing attribute 'analyzerPath'");
    }
    if(!isset($this->file) and count($this->filesets) == 0) {
      throw new BuildException("Missing either a nested fileset or attribute 'file' set");
    }
    
    if($this->file instanceof PhingFile) {
      $this->analyze($this->file->getPath());
    } else { // process filesets
      $project = $this->getProject();
      foreach($this->filesets as $fs) {
      	$ds = $fs->getDirectoryScanner($project);
      	$files = $ds->getIncludedFiles();
      	$dir = $fs->getDir($this->project)->getPath();
      	foreach($files as $file) {
	  $this->analyze($dir.DIRECTORY_SEPARATOR.$file);
      	}
      }
    }
    $this->log("Number of findings: ".$this->counter, PROJECT_MSG_INFO);
  }

  /**
   * Analyze file
   *
   * @param string $file
   * @return void
   */
  protected function analyze($file) {
    if(file_exists($file)) {
      if(is_readable($file)) {
      	
      	// Construct shell command
      	$cmd = $this->analyzerPath." ";
      	foreach($this->enable as $enable) { // Enable warning levels
      		$cmd .= " --enable $enable ";
      	}
      	foreach($this->disable as $disable) { // Disable warning levels
      		$cmd .= " --disable $disable ";
      	}
      	$cmd .= "$file 2>&1";
      	
      	// Execute command
      	$result = shell_exec($cmd);
      	$result = explode("\n", $result);
      	for($i=2, $size=count($result); $i<($size-1); $i++) {
	  $this->counter++;
	  $this->log($result[$i], PROJECT_MSG_WARN);
      	}
      } else {
      	throw new BuildException('Permission denied: '.$file);
      }
    } else {
      throw new BuildException('File not found: '.$file);
    }
  }
}

?>