1<?php 2/** 3 * Readability Analysis Plugin for DokuWiki 4 * 5 * @author Andreas Gohr <andi@splitbrain.org> 6 * @author Dave Child <dave@ilovejackdaniels.com> 7 * @link http://www.ilovejackdaniels.com/resources/readability-score/ 8 * @license GPL 2 9 */ 10 11 12$text = $_REQUEST['html'].'. '; 13$text = preg_replace('!</(li|h[1-5])>!i','. ',$text); //make sentences from those tags 14$text = strip_tags($text); 15 16$gf = gunning_fog_score($text); 17$fs = calculate_flesch($text); 18$fg = calculate_flesch_grade($text); 19$rt = calculate_readingtime($text); 20 21echo '<b>Readability Analysis</b>'; 22echo '<ul>'; 23printf('<li><div class="li"><b>Gunning-Fog Score:</b> %.2f ',$gf); 24if($gf < 12){ 25 echo '(very good)'; 26}elseif($gf < 15){ 27 echo '(okay)'; 28}else{ 29 echo '(bad)'; 30} 31echo ' lower is better'; 32echo '</div></li>'; 33printf('<li><div class="li"><b>Flesch-Kincaid Score:</b> %.2f ',$fs); 34if($fs < 50){ 35 echo '(bad)'; 36}elseif($fs < 80){ 37 echo '(okay)'; 38}else{ 39 echo '(very good)'; 40} 41echo ' higher is better'; 42echo '</div></li>'; 43printf('<li><div class="li"><b>Flesch-Kincaid Grade:</b> %.2f ',$fg); 44if($fg < 10){ 45 echo '(very good)'; 46}elseif($fg < 18){ 47 echo '(okay)'; 48}else{ 49 echo '(bad)'; 50} 51echo ' lower is better'; 52echo '</div></li>'; 53echo '<li><div class="li"><b>Estimated reading time:</b> '.$rt.'</div></li>'; 54echo '</ul>'; 55 56/** 57 * Calculate estimated reading time 58 * 59 * @author Brian Cray 60 * @link http://briancray.com/2010/04/09/estimated-reading-time-web-design/ 61 */ 62function calculate_readingtime($text){ 63 $word = str_word_count($text); 64 $m = floor($word / 200); 65 $s = floor($word % 200 / (200 / 60)); 66 return "$m:$s"; 67} 68 69/** 70 * Calculate the Gunning-Fog score 71 * 72 * @author Dave Child <dave@ilovejackdaniels.com> 73 */ 74function gunning_fog_score($text) { 75 return ((average_words_sentence($text) + 76 percentage_number_words_three_syllables($text)) * 0.4); 77} 78 79/** 80 * Calculate the Flesch-Kinkaid reading ease score 81 * 82 * @author Dave Child <dave@ilovejackdaniels.com> 83 */ 84function calculate_flesch($text) { 85 return (206.835 - (1.015 * average_words_sentence($text)) - 86 (84.6 * average_syllables_word($text))); 87} 88 89/** 90 * Calculate the Flesch-Kinkaid Grade level 91 * 92 * @author Dave Child <dave@ilovejackdaniels.com> 93 */ 94function calculate_flesch_grade($text) { 95 return ((.39 * average_words_sentence($text)) + 96 (11.8 * average_syllables_word($text)) - 15.59); 97} 98 99/** 100 * Calculate the percentage of words with more than 3 syllables 101 * 102 * @author Dave Child <dave@ilovejackdaniels.com> 103 */ 104function percentage_number_words_three_syllables($text) { 105 $syllables = 0; 106 $words = explode(' ', $text); 107 for ($i = 0; $i < count($words); $i++) { 108 if (count_syllables($words[$i]) > 2) { 109 $syllables ++; 110 } 111 } 112 $score = number_format((($syllables / count($words)) * 100)); 113 114 return ($score); 115} 116 117/** 118 * Calculate the ratio of words to sentences 119 * 120 * @author Dave Child <dave@ilovejackdaniels.com> 121 */ 122function average_words_sentence($text) { 123 $sentences = strlen(preg_replace('/[^\.!?]/', '', $text)); 124 $words = strlen(preg_replace('/[^ ]/', '', $text)); 125 if($sentences == 0) $sentences = 1; 126 return ($words/$sentences); 127} 128 129/** 130 * Calculate the average number of syllables per word 131 * 132 * @author Dave Child <dave@ilovejackdaniels.com> 133 */ 134function average_syllables_word($text) { 135 $words = explode(' ', $text); 136 $syllables = 0; 137 for ($i = 0; $i < count($words); $i++) { 138 $syllables = $syllables + count_syllables($words[$i]); 139 } 140 return ($syllables/count($words)); 141} 142 143/** 144 * Count the number of syllables in the given word 145 * 146 * @author Dave Child <dave@ilovejackdaniels.com> 147 */ 148function count_syllables($word) { 149 150 $subsyl = Array( 151 'cial', 152 'tia', 153 'cius', 154 'cious', 155 'giu', 156 'ion', 157 'iou', 158 'sia$', 159 '.ely$' 160 ); 161 162 $addsyl = Array( 163 'ia', 164 'riet', 165 'dien', 166 'iu', 167 'io', 168 'ii', 169 '[aeiouym]bl$', 170 '[aeiou]{3}', 171 '^mc', 172 'ism$', 173 '([^aeiouy])\1l$', 174 '[^l]lien', 175 '^coa[dglx].', 176 '[^gq]ua[^auieo]', 177 'dnt$' 178 ); 179 180 // Based on Greg Fast's Perl module Lingua::EN::Syllables 181 $word = preg_replace('/[^a-z]/is', '', strtolower($word)); 182 $word_parts = preg_split('/[^aeiouy]+/', $word); 183 $valid_word_parts = array(); 184 foreach ($word_parts as $key => $value) { 185 if ($value <> '') { 186 $valid_word_parts[] = $value; 187 } 188 } 189 190 $syllables = 0; 191 foreach ($subsyl as $syl) { 192 if (strpos($word, $syl) !== false) { 193 $syllables--; 194 } 195 } 196 foreach ($addsyl as $syl) { 197 if (strpos($word, $syl) !== false) { 198 $syllables++; 199 } 200 } 201 if (strlen($word) == 1) { 202 $syllables++; 203 } 204 $syllables += count($valid_word_parts); 205 $syllables = ($syllables == 0) ? 1 : $syllables; 206 return $syllables; 207} 208 209 210