See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Check that, as in the coding guidelines, every to-do comment links to a tracker issue. 19 * 20 * As required by https://moodledev.io/general/development/policies/codingstyle. 21 * 22 * @package core 23 * @copyright 2009 Tim Hunt 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 25 */ 26 27 require(__DIR__ . '/../../../config.php'); 28 29 require_login(); 30 $context = context_system::instance(); 31 require_capability('moodle/site:config', $context); 32 33 $PAGE->set_url('/lib/tests/other/todochecker.php'); 34 $PAGE->set_context($context); 35 $PAGE->set_title('To-do checker'); 36 $PAGE->set_heading('To-do checker'); 37 38 $thirdparty = load_third_party_lib_list(); 39 $extensionstotest = array('php'); 40 $extensionsregex = '/\.(?:' . implode('|', $extensionstotest) . ')$/'; 41 $patterntofind = 'TO' . 'DO'; // Make it not match the regex. 42 $found = array(); 43 44 echo $OUTPUT->header(); 45 echo $OUTPUT->heading('To-do checker', 2); 46 47 echo $OUTPUT->box_start(); 48 echo 'Checking code ...'; 49 flush(); 50 recurseFolders($CFG->dirroot, 'check_to_dos', $extensionsregex, false, array_keys($thirdparty)); 51 echo ' done.'; 52 echo $OUTPUT->box_end(); 53 54 if (empty($found)) { 55 echo '<p>No to-dos found.</p>'; 56 } else { 57 $total = 0; 58 foreach ($found as $filepath => $matches) { 59 $total += count($matches); 60 } 61 62 echo '<p>' . $total . ' to-dos found:</p><dl>'; 63 foreach ($found as $filepath => $matches) { 64 echo '<dt>' . $filepath . ' <b>(' . count($matches) . ')</b></dt><dd><ul>'; 65 foreach ($matches as $lineno => $line) { 66 $url = 'http://cvs.moodle.org/moodle/' . $filepath . '?view=annotate#l' . $lineno; 67 $error = ''; 68 69 // Make sure there is a tracker issue id mentioned 70 $matches = array(); 71 if (preg_match('/\bTODO\b.*?\b(MDL-\d+)/', $line, $matches)) { 72 $issueid = $matches[1]; 73 $issueurl = 'http://tracker.moodle.org/browse/' . $issueid; 74 75 // Make sure the issue is still open. 76 list($issueopen, $issuesummary) = issue_info($issueid); 77 if ($issueopen) { 78 $issuename = $issueid; 79 } else { 80 $issuename = '<strike>' . $issueid . '</strike>'; 81 $error = 'The associated tracker issue is Resolved.'; 82 } 83 84 $line = str_replace($issueid, '<a href="' . $issueurl . '" title="' . s($issuesummary) . 85 '">' . $issuename . '</a>', htmlspecialchars($line, ENT_COMPAT)); 86 } else { 87 $line = htmlspecialchars($line, ENT_COMPAT); 88 $error = 'No associated tracker issue.'; 89 } 90 91 if ($error) { 92 $error = '<span class="error">' . $error . '</span>'; 93 } 94 echo '<li><a href="' . $url . '">' . $lineno . '</a>: ' . $line . $error . '</li>'; 95 } 96 echo '</ul></dd>'; 97 } 98 echo '</dl>'; 99 } 100 101 echo $OUTPUT->footer(); 102 103 function check_to_dos($filepath) { 104 global $CFG, $found, $thirdparty; 105 if (isset($thirdparty[$filepath])) { 106 return; // Skip this file. 107 } 108 $lines = file($filepath); 109 $matchesinfile = array(); 110 foreach ($lines as $lineno => $line) { 111 if (preg_match('/(?<!->|\$)\bTODO\b/i', $line)) { 112 $matchesinfile[$lineno] = $line; 113 } 114 } 115 if (!empty($matchesinfile)) { 116 $shortpath = str_replace($CFG->dirroot . '/', '', $filepath); 117 $found[$shortpath] = $matchesinfile; 118 } 119 } 120 121 function issue_info($issueid) { 122 static $cache = array(); 123 if (array_key_exists($issueid, $cache)) { 124 return $cache[$issueid]; 125 } 126 127 $xmlurl = 'http://tracker.moodle.org/si/jira.issueviews:issue-xml/' . $issueid . '/' . $issueid . '.xml'; 128 $content = download_file_content($xmlurl); 129 130 // Get the status. 131 $open = preg_match('/Unresolved<\/resolution>/', $content); 132 133 // Get the summary. 134 $matches = array(); 135 preg_match('/<title>\[' . $issueid . '\]\s+(.*?)<\/title>/', $content, $matches); 136 $summary = $matches[1]; 137 preg_match('/<assignee[^>]*>(.*?)<\/assignee>/', $content, $matches); 138 $summary .= ' - Assignee: ' . $matches[1]; 139 140 $cache[$issueid] = array($open, $summary); 141 return $cache[$issueid]; 142 } 143 144 function load_third_party_lib_list() { 145 global $CFG; 146 $libs = array(); 147 $xml = simplexml_load_file($CFG->libdir . '/thirdpartylibs.xml'); 148 foreach ($xml->library as $libobject) { 149 $libs[$CFG->libdir . '/' . $libobject->location] = 1; 150 } 151 return $libs; 152 } 153 154 function recurseFolders($path, $callback, $fileregexp = '/.*/', $exclude = false, $ignorefolders = array()) { 155 $files = scandir($path); 156 157 foreach ($files as $file) { 158 $filepath = $path .'/'. $file; 159 if (strpos($file, '.') === 0) { 160 /// Don't check hidden files. 161 continue; 162 } else if (is_dir($filepath)) { 163 if (!in_array($filepath, $ignorefolders)) { 164 recurseFolders($filepath, $callback, $fileregexp, $exclude, $ignorefolders); 165 } 166 } else if ($exclude xor preg_match($fileregexp, $filepath)) { 167 call_user_func($callback, $filepath); 168 } 169 } 170 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body