Commit 02245a28 by Scott Vivian

Add new autoloaded classes Q2A_Util_Usage and Q2A_Util_String

Debugging functions converted to use Usage.
String class not yet in use.
parent 5db31475
<?php
/*
Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/
License: GPLv2+ <http://www.question2answer.org/license.php>
File: qa-include/Util/String.php
Description: Some useful string-related stuff
*/
class Q2A_Util_String
{
/**
* Notable exclusions here: $ & - _ # % @
*/
private static $pregIndexWordSeparator = '[\n\r\t\ \!\"\\\'\(\)\*\+\,\.\/\:\;\<\=\>\?\[\\\\\]\^\`\{\|\}\~]';
/**
* Asterisk (*) excluded here because it's used to match anything
*/
private static $pregBlockWordSeparator = '[\n\r\t\ \!\"\\\'\(\)\+\,\.\/\:\;\<\=\>\?\[\\\\\]\^\`\{\|\}\~\$\&\-\_\#\%\@]';
/**
* Pattern to match Chinese/Japanese/Korean ideographic symbols in UTF-8 encoding
*/
private static $pregCjkIdeographsUtf8 = '\xE2[\xBA-\xBF][\x80-\xBF]|\xE3[\x80\x88-\xBF][\x80-\xBF]|[\xE4-\xE9][\x80-\xBF][\x80-\xBF]|\xEF[\xA4-\xAB][\x80-\xBF]|\xF0[\xA0-\xAF][\x80-\xBF][\x80-\xBF]';
/**
* Holder for keep-length data
*/
private static $utf8PunctuationKeepLength = array();
/**
* Converts UTF-8 punctuation characters to spaces (or in some cases, hyphens)
*/
private static $utf8Punctuation = array(
"\xC2\xA1" => ' ', // INVERTED EXCLAMATION MARK
"\xC2\xA6" => ' ', // BROKEN BAR
"\xC2\xAB" => ' ', // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
"\xC2\xB1" => ' ', // PLUS-MINUS SIGN
"\xC2\xBB" => ' ', // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
"\xC2\xBF" => ' ', // INVERTED QUESTION MARK
"\xC3\x97" => ' ', // MULTIPLICATION SIGN
"\xC3\xB7" => ' ', // DIVISION SIGN
"\xE2\x80\x80" => ' ', // EN QUAD
"\xE2\x80\x81" => ' ', // EM QUAD
"\xE2\x80\x82" => ' ', // EN SPACE
"\xE2\x80\x83" => ' ', // EM SPACE
"\xE2\x80\x84" => ' ', // THREE-PER-EM SPACE
"\xE2\x80\x85" => ' ', // FOUR-PER-EM SPACE
"\xE2\x80\x86" => ' ', // SIX-PER-EM SPACE
"\xE2\x80\x87" => ' ', // FIGURE SPACE
"\xE2\x80\x88" => ' ', // PUNCTUATION SPACE
"\xE2\x80\x89" => ' ', // THIN SPACE
"\xE2\x80\x8A" => ' ', // HAIR SPACE
"\xE2\x80\x8B" => ' ', // ZERO WIDTH SPACE
"\xE2\x80\x8C" => ' ', // ZERO WIDTH NON-JOINER
"\xE2\x80\x8E" => ' ', // LEFT-TO-RIGHT MARK
"\xE2\x80\x8F" => ' ', // RIGHT-TO-LEFT MARK
"\xE2\x80\x90" => '-', // HYPHEN
"\xE2\x80\x91" => '-', // NON-BREAKING HYPHEN
"\xE2\x80\x92" => '-', // FIGURE DASH
"\xE2\x80\x93" => '-', // EN DASH
"\xE2\x80\x94" => '-', // EM DASH
"\xE2\x80\x95" => '-', // HORIZONTAL BAR
"\xE2\x80\x96" => ' ', // DOUBLE VERTICAL LINE
"\xE2\x80\x98" => ' ', // LEFT SINGLE QUOTATION MARK
"\xE2\x80\x99" => "'", // RIGHT SINGLE QUOTATION MARK
"\xE2\x80\x9A" => ' ', // SINGLE LOW-9 QUOTATION MARK
"\xE2\x80\x9B" => ' ', // SINGLE HIGH-REVERSED-9 QUOTATION MARK
"\xE2\x80\x9C" => ' ', // LEFT DOUBLE QUOTATION MARK
"\xE2\x80\x9D" => ' ', // RIGHT DOUBLE QUOTATION MARK
"\xE2\x80\x9E" => ' ', // DOUBLE LOW-9 QUOTATION MARK
"\xE2\x80\x9F" => ' ', // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
"\xE2\x80\xA2" => ' ', // BULLET
"\xE2\x80\xA4" => ' ', // ONE DOT LEADER
"\xE2\x80\xA5" => ' ', // TWO DOT LEADER
"\xE2\x80\xA6" => ' ', // HORIZONTAL ELLIPSIS
"\xE2\x80\xB9" => ' ', // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
"\xE2\x80\xBA" => ' ', // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
"\xE2\x80\xBC" => ' ', // DOUBLE EXCLAMATION MARK
"\xE2\x80\xBD" => ' ', // INTERROBANG
"\xE2\x81\x87" => ' ', // DOUBLE QUESTION MARK
"\xE2\x81\x88" => ' ', // QUESTION EXCLAMATION MARK
"\xE2\x81\x89" => ' ', // EXCLAMATION QUESTION MARK
"\xE3\x80\x80" => ' ', // IDEOGRAPHIC SPACE
"\xE3\x80\x81" => ' ', // IDEOGRAPHIC COMMA
"\xE3\x80\x82" => ' ', // IDEOGRAPHIC FULL STOP
);
/**
* Convert UTF-8 accented characters to basic Roman characters
*/
private static $utf8RemoveAccents = array(
"\xC3\x80" => 'A', // LATIN CAPITAL LETTER A WITH GRAVE
"\xC3\x81" => 'A', // LATIN CAPITAL LETTER A WITH ACUTE
"\xC3\x82" => 'A', // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
"\xC3\x83" => 'A', // LATIN CAPITAL LETTER A WITH TILDE
"\xC3\x84" => 'A', // LATIN CAPITAL LETTER A WITH DIAERESIS
"\xC3\x85" => 'A', // LATIN CAPITAL LETTER A WITH RING ABOVE
"\xC3\x86" => 'AE', // LATIN CAPITAL LETTER AE
"\xC3\x87" => 'C', // LATIN CAPITAL LETTER C WITH CEDILLA
"\xC3\x88" => 'E', // LATIN CAPITAL LETTER E WITH GRAVE
"\xC3\x89" => 'E', // LATIN CAPITAL LETTER E WITH ACUTE
"\xC3\x8A" => 'E', // LATIN CAPITAL LETTER E WITH CIRCUMFLEX
"\xC3\x8B" => 'E', // LATIN CAPITAL LETTER E WITH DIAERESIS
"\xC3\x8C" => 'I', // LATIN CAPITAL LETTER I WITH GRAVE
"\xC3\x8D" => 'I', // LATIN CAPITAL LETTER I WITH ACUTE
"\xC3\x8E" => 'I', // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
"\xC3\x8F" => 'I', // LATIN CAPITAL LETTER I WITH DIAERESIS
"\xC3\x91" => 'N', // LATIN CAPITAL LETTER N WITH TILDE
"\xC3\x92" => 'O', // LATIN CAPITAL LETTER O WITH GRAVE
"\xC3\x93" => 'O', // LATIN CAPITAL LETTER O WITH ACUTE
"\xC3\x94" => 'O', // LATIN CAPITAL LETTER O WITH CIRCUMFLEX
"\xC3\x95" => 'O', // LATIN CAPITAL LETTER O WITH TILDE
"\xC3\x96" => 'O', // LATIN CAPITAL LETTER O WITH DIAERESIS
"\xC3\x98" => 'O', // LATIN CAPITAL LETTER O WITH STROKE
"\xC3\x99" => 'U', // LATIN CAPITAL LETTER U WITH GRAVE
"\xC3\x9A" => 'U', // LATIN CAPITAL LETTER U WITH ACUTE
"\xC3\x9B" => 'U', // LATIN CAPITAL LETTER U WITH CIRCUMFLEX
"\xC3\x9C" => 'U', // LATIN CAPITAL LETTER U WITH DIAERESIS
"\xC3\x9D" => 'Y', // LATIN CAPITAL LETTER Y WITH ACUTE
"\xC3\x9F" => 'ss', // LATIN SMALL LETTER SHARP S
"\xC3\xA0" => 'a', // LATIN SMALL LETTER A WITH GRAVE
"\xC3\xA1" => 'a', // LATIN SMALL LETTER A WITH ACUTE
"\xC3\xA2" => 'a', // LATIN SMALL LETTER A WITH CIRCUMFLEX
"\xC3\xA3" => 'a', // LATIN SMALL LETTER A WITH TILDE
"\xC3\xA4" => 'a', // LATIN SMALL LETTER A WITH DIAERESIS
"\xC3\xA5" => 'a', // LATIN SMALL LETTER A WITH RING ABOVE
"\xC3\xA6" => 'ae', // LATIN SMALL LETTER AE
"\xC3\xA7" => 'c', // LATIN SMALL LETTER C WITH CEDILLA
"\xC3\xA8" => 'e', // LATIN SMALL LETTER E WITH GRAVE
"\xC3\xA9" => 'e', // LATIN SMALL LETTER E WITH ACUTE
"\xC3\xAA" => 'e', // LATIN SMALL LETTER E WITH CIRCUMFLEX
"\xC3\xAB" => 'e', // LATIN SMALL LETTER E WITH DIAERESIS
"\xC3\xAC" => 'i', // LATIN SMALL LETTER I WITH GRAVE
"\xC3\xAD" => 'i', // LATIN SMALL LETTER I WITH ACUTE
"\xC3\xAE" => 'i', // LATIN SMALL LETTER I WITH CIRCUMFLEX
"\xC3\xAF" => 'i', // LATIN SMALL LETTER I WITH DIAERESIS
"\xC3\xB1" => 'n', // LATIN SMALL LETTER N WITH TILDE
"\xC3\xB2" => 'o', // LATIN SMALL LETTER O WITH GRAVE
"\xC3\xB3" => 'o', // LATIN SMALL LETTER O WITH ACUTE
"\xC3\xB4" => 'o', // LATIN SMALL LETTER O WITH CIRCUMFLEX
"\xC3\xB5" => 'o', // LATIN SMALL LETTER O WITH TILDE
"\xC3\xB6" => 'o', // LATIN SMALL LETTER O WITH DIAERESIS
"\xC3\xB8" => 'o', // LATIN SMALL LETTER O WITH STROKE
"\xC3\xB9" => 'u', // LATIN SMALL LETTER U WITH GRAVE
"\xC3\xBA" => 'u', // LATIN SMALL LETTER U WITH ACUTE
"\xC3\xBB" => 'u', // LATIN SMALL LETTER U WITH CIRCUMFLEX
"\xC3\xBC" => 'u', // LATIN SMALL LETTER U WITH DIAERESIS
"\xC3\xBD" => 'y', // LATIN SMALL LETTER Y WITH ACUTE
"\xC3\xBF" => 'y', // LATIN SMALL LETTER Y WITH DIAERESIS
"\xC4\x80" => 'A', // LATIN CAPITAL LETTER A WITH MACRON
"\xC4\x81" => 'a', // LATIN SMALL LETTER A WITH MACRON
"\xC4\x82" => 'A', // LATIN CAPITAL LETTER A WITH BREVE
"\xC4\x83" => 'a', // LATIN SMALL LETTER A WITH BREVE
"\xC4\x84" => 'A', // LATIN CAPITAL LETTER A WITH OGONEK
"\xC4\x85" => 'a', // LATIN SMALL LETTER A WITH OGONEK
"\xC4\x86" => 'C', // LATIN CAPITAL LETTER C WITH ACUTE
"\xC4\x87" => 'c', // LATIN SMALL LETTER C WITH ACUTE
"\xC4\x88" => 'C', // LATIN CAPITAL LETTER C WITH CIRCUMFLEX
"\xC4\x89" => 'c', // LATIN SMALL LETTER C WITH CIRCUMFLEX
"\xC4\x8A" => 'C', // LATIN CAPITAL LETTER C WITH DOT ABOVE
"\xC4\x8B" => 'c', // LATIN SMALL LETTER C WITH DOT ABOVE
"\xC4\x8C" => 'C', // LATIN CAPITAL LETTER C WITH CARON
"\xC4\x8D" => 'c', // LATIN SMALL LETTER C WITH CARON
"\xC4\x8E" => 'D', // LATIN CAPITAL LETTER D WITH CARON
"\xC4\x8F" => 'd', // LATIN SMALL LETTER D WITH CARON
"\xC4\x90" => 'D', // LATIN CAPITAL LETTER D WITH STROKE
"\xC4\x91" => 'd', // LATIN SMALL LETTER D WITH STROKE
"\xC4\x92" => 'E', // LATIN CAPITAL LETTER E WITH MACRON
"\xC4\x93" => 'e', // LATIN SMALL LETTER E WITH MACRON
"\xC4\x94" => 'E', // LATIN CAPITAL LETTER E WITH BREVE
"\xC4\x95" => 'e', // LATIN SMALL LETTER E WITH BREVE
"\xC4\x96" => 'E', // LATIN CAPITAL LETTER E WITH DOT ABOVE
"\xC4\x97" => 'e', // LATIN SMALL LETTER E WITH DOT ABOVE
"\xC4\x98" => 'E', // LATIN CAPITAL LETTER E WITH OGONEK
"\xC4\x99" => 'e', // LATIN SMALL LETTER E WITH OGONEK
"\xC4\x9A" => 'E', // LATIN CAPITAL LETTER E WITH CARON
"\xC4\x9B" => 'e', // LATIN SMALL LETTER E WITH CARON
"\xC4\x9C" => 'G', // LATIN CAPITAL LETTER G WITH CIRCUMFLEX
"\xC4\x9D" => 'g', // LATIN SMALL LETTER G WITH CIRCUMFLEX
"\xC4\x9E" => 'G', // LATIN CAPITAL LETTER G WITH BREVE
"\xC4\x9F" => 'g', // LATIN SMALL LETTER G WITH BREVE
"\xC4\xA0" => 'G', // LATIN CAPITAL LETTER G WITH DOT ABOVE
"\xC4\xA1" => 'g', // LATIN SMALL LETTER G WITH DOT ABOVE
"\xC4\xA2" => 'G', // LATIN CAPITAL LETTER G WITH CEDILLA
"\xC4\xA3" => 'g', // LATIN SMALL LETTER G WITH CEDILLA
"\xC4\xA4" => 'H', // LATIN CAPITAL LETTER H WITH CIRCUMFLEX
"\xC4\xA5" => 'h', // LATIN SMALL LETTER H WITH CIRCUMFLEX
"\xC4\xA6" => 'H', // LATIN CAPITAL LETTER H WITH STROKE
"\xC4\xA7" => 'h', // LATIN SMALL LETTER H WITH STROKE
"\xC4\xA8" => 'I', // LATIN CAPITAL LETTER I WITH TILDE
"\xC4\xA9" => 'i', // LATIN SMALL LETTER I WITH TILDE
"\xC4\xAA" => 'I', // LATIN CAPITAL LETTER I WITH MACRON
"\xC4\xAB" => 'i', // LATIN SMALL LETTER I WITH MACRON
"\xC4\xAC" => 'I', // LATIN CAPITAL LETTER I WITH BREVE
"\xC4\xAD" => 'i', // LATIN SMALL LETTER I WITH BREVE
"\xC4\xAE" => 'I', // LATIN CAPITAL LETTER I WITH OGONEK
"\xC4\xAF" => 'i', // LATIN SMALL LETTER I WITH OGONEK
"\xC4\xB0" => 'I', // LATIN CAPITAL LETTER I WITH DOT ABOVE
"\xC4\xB1" => 'i', // LATIN SMALL LETTER DOTLESS I
"\xC4\xB2" => 'IJ', // LATIN CAPITAL LIGATURE IJ
"\xC4\xB3" => 'ij', // LATIN SMALL LIGATURE IJ
"\xC4\xB4" => 'j', // LATIN CAPITAL LETTER J WITH CIRCUMFLEX
"\xC4\xB5" => 'j', // LATIN SMALL LETTER J WITH CIRCUMFLEX
"\xC4\xB6" => 'K', // LATIN CAPITAL LETTER K WITH CEDILLA
"\xC4\xB7" => 'k', // LATIN SMALL LETTER K WITH CEDILLA
"\xC4\xB9" => 'L', // LATIN CAPITAL LETTER L WITH ACUTE
"\xC4\xBA" => 'l', // LATIN SMALL LETTER L WITH ACUTE
"\xC4\xBB" => 'L', // LATIN CAPITAL LETTER L WITH CEDILLA
"\xC4\xBC" => 'l', // LATIN SMALL LETTER L WITH CEDILLA
"\xC4\xBD" => 'L', // LATIN CAPITAL LETTER L WITH CARON
"\xC4\xBE" => 'l', // LATIN SMALL LETTER L WITH CARON
"\xC4\xBF" => 'L', // LATIN CAPITAL LETTER L WITH MIDDLE DOT
"\xC5\x80" => 'l', // LATIN SMALL LETTER L WITH MIDDLE DOT
"\xC5\x81" => 'L', // LATIN CAPITAL LETTER L WITH STROKE
"\xC5\x82" => 'l', // LATIN SMALL LETTER L WITH STROKE
"\xC5\x83" => 'N', // LATIN CAPITAL LETTER N WITH ACUTE
"\xC5\x84" => 'n', // LATIN SMALL LETTER N WITH ACUTE
"\xC5\x85" => 'N', // LATIN CAPITAL LETTER N WITH CEDILLA
"\xC5\x86" => 'n', // LATIN SMALL LETTER N WITH CEDILLA
"\xC5\x87" => 'N', // LATIN CAPITAL LETTER N WITH CARON
"\xC5\x88" => 'n', // LATIN SMALL LETTER N WITH CARON
"\xC5\x8C" => 'O', // LATIN CAPITAL LETTER O WITH MACRON
"\xC5\x8D" => 'o', // LATIN SMALL LETTER O WITH MACRON
"\xC5\x8E" => 'O', // LATIN CAPITAL LETTER O WITH BREVE
"\xC5\x8F" => 'o', // LATIN SMALL LETTER O WITH BREVE
"\xC5\x90" => 'O', // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
"\xC5\x91" => 'o', // LATIN SMALL LETTER O WITH DOUBLE ACUTE
"\xC5\x92" => 'OE', // LATIN CAPITAL LIGATURE OE
"\xC5\x93" => 'oe', // LATIN SMALL LIGATURE OE
"\xC5\x94" => 'R', // LATIN CAPITAL LETTER R WITH ACUTE
"\xC5\x95" => 'r', // LATIN SMALL LETTER R WITH ACUTE
"\xC5\x96" => 'R', // LATIN CAPITAL LETTER R WITH CEDILLA
"\xC5\x97" => 'r', // LATIN SMALL LETTER R WITH CEDILLA
"\xC5\x98" => 'R', // LATIN CAPITAL LETTER R WITH CARON
"\xC5\x99" => 'r', // LATIN SMALL LETTER R WITH CARON
"\xC5\x9A" => 'S', // LATIN CAPITAL LETTER S WITH ACUTE
"\xC5\x9B" => 's', // LATIN SMALL LETTER S WITH ACUTE
"\xC5\x9C" => 'S', // LATIN CAPITAL LETTER S WITH CIRCUMFLEX
"\xC5\x9D" => 's', // LATIN SMALL LETTER S WITH CIRCUMFLEX
"\xC5\x9E" => 'S', // LATIN CAPITAL LETTER S WITH CEDILLA
"\xC5\x9F" => 's', // LATIN SMALL LETTER S WITH CEDILLA
"\xC5\xA0" => 'S', // LATIN CAPITAL LETTER S WITH CARON
"\xC5\xA1" => 's', // LATIN SMALL LETTER S WITH CARON
"\xC5\xA2" => 'T', // LATIN CAPITAL LETTER T WITH CEDILLA
"\xC5\xA3" => 't', // LATIN SMALL LETTER T WITH CEDILLA
"\xC5\xA4" => 'T', // LATIN CAPITAL LETTER T WITH CARON
"\xC5\xA5" => 't', // LATIN SMALL LETTER T WITH CARON
"\xC5\xA6" => 'T', // LATIN CAPITAL LETTER T WITH STROKE
"\xC5\xA7" => 't', // LATIN SMALL LETTER T WITH STROKE
"\xC5\xA8" => 'U', // LATIN CAPITAL LETTER U WITH TILDE
"\xC5\xA9" => 'u', // LATIN SMALL LETTER U WITH TILDE
"\xC5\xAA" => 'U', // LATIN CAPITAL LETTER U WITH MACRON
"\xC5\xAB" => 'u', // LATIN SMALL LETTER U WITH MACRON
"\xC5\xAC" => 'U', // LATIN CAPITAL LETTER U WITH BREVE
"\xC5\xAD" => 'u', // LATIN SMALL LETTER U WITH BREVE
"\xC5\xAE" => 'U', // LATIN CAPITAL LETTER U WITH RING ABOVE
"\xC5\xAF" => 'u', // LATIN SMALL LETTER U WITH RING ABOVE
"\xC5\xB0" => 'U', // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
"\xC5\xB1" => 'u', // LATIN SMALL LETTER U WITH DOUBLE ACUTE
"\xC5\xB2" => 'U', // LATIN CAPITAL LETTER U WITH OGONEK
"\xC5\xB3" => 'u', // LATIN SMALL LETTER U WITH OGONEK
"\xC5\xB4" => 'W', // LATIN CAPITAL LETTER W WITH CIRCUMFLEX
"\xC5\xB5" => 'w', // LATIN SMALL LETTER W WITH CIRCUMFLEX
"\xC5\xB6" => 'Y', // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
"\xC5\xB7" => 'y', // LATIN SMALL LETTER Y WITH CIRCUMFLEX
"\xC5\xB8" => 'Y', // LATIN CAPITAL LETTER Y WITH DIAERESIS
"\xC5\xB9" => 'Z', // LATIN CAPITAL LETTER Z WITH ACUTE
"\xC5\xBA" => 'z', // LATIN SMALL LETTER Z WITH ACUTE
"\xC5\xBB" => 'Z', // LATIN CAPITAL LETTER Z WITH DOT ABOVE
"\xC5\xBC" => 'z', // LATIN SMALL LETTER Z WITH DOT ABOVE
"\xC5\xBD" => 'Z', // LATIN CAPITAL LETTER Z WITH CARON
"\xC5\xBE" => 'z', // LATIN SMALL LETTER Z WITH CARON
"\xC6\x80" => 'b', // LATIN SMALL LETTER B WITH STROKE
"\xC6\x81" => 'B', // LATIN CAPITAL LETTER B WITH HOOK
"\xC6\x82" => 'B', // LATIN CAPITAL LETTER B WITH TOPBAR
"\xC6\x83" => 'b', // LATIN SMALL LETTER B WITH TOPBAR
"\xC6\x87" => 'C', // LATIN CAPITAL LETTER C WITH HOOK
"\xC6\x88" => 'c', // LATIN SMALL LETTER C WITH HOOK
"\xC6\x89" => 'D', // LATIN CAPITAL LETTER AFRICAN D
"\xC6\x8A" => 'D', // LATIN CAPITAL LETTER D WITH HOOK
"\xC6\x8B" => 'D', // LATIN CAPITAL LETTER D WITH TOPBAR
"\xC6\x8C" => 'd', // LATIN SMALL LETTER D WITH TOPBAR
"\xC6\x91" => 'F', // LATIN CAPITAL LETTER F WITH HOOK
"\xC6\x92" => 'f', // LATIN SMALL LETTER F WITH HOOK
"\xC6\x93" => 'G', // LATIN CAPITAL LETTER G WITH HOOKU+0195
"\xC6\x97" => 'I', // LATIN CAPITAL LETTER I WITH STROKE
"\xC6\x98" => 'K', // LATIN CAPITAL LETTER K WITH HOOK
"\xC6\x99" => 'k', // LATIN SMALL LETTER K WITH HOOK
"\xC6\x9A" => 'l', // LATIN SMALL LETTER L WITH BAR
"\xC6\x9D" => 'N', // LATIN CAPITAL LETTER N WITH LEFT HOOK
"\xC6\x9E" => 'n', // LATIN SMALL LETTER N WITH LONG RIGHT LEG
"\xC6\x9F" => 'O', // LATIN CAPITAL LETTER O WITH MIDDLE TILDE
"\xC6\xA0" => 'O', // LATIN CAPITAL LETTER O WITH HORN
"\xC6\xA1" => 'o', // LATIN SMALL LETTER O WITH HORN
"\xC6\xA2" => 'OI', // LATIN CAPITAL LETTER OI
"\xC6\xA3" => 'oi', // LATIN SMALL LETTER OI
"\xC6\xA4" => 'P', // LATIN CAPITAL LETTER P WITH HOOK
"\xC6\xA5" => 'p', // LATIN SMALL LETTER P WITH HOOK
"\xC6\xAB" => 't', // LATIN SMALL LETTER T WITH PALATAL HOOK
"\xC6\xAC" => 'T', // LATIN CAPITAL LETTER T WITH HOOK
"\xC6\xAD" => 't', // LATIN SMALL LETTER T WITH HOOK
"\xC6\xAE" => 'T', // LATIN CAPITAL LETTER T WITH RETROFLEX HOOK
"\xC6\xAF" => 'U', // LATIN CAPITAL LETTER U WITH HORN
"\xC6\xB0" => 'u', // LATIN SMALL LETTER U WITH HORN
"\xC6\xB2" => 'V', // LATIN CAPITAL LETTER V WITH HOOK
"\xC6\xB3" => 'Y', // LATIN CAPITAL LETTER Y WITH HOOK
"\xC6\xB4" => 'y', // LATIN SMALL LETTER Y WITH HOOK
"\xC6\xB5" => 'Z', // LATIN CAPITAL LETTER Z WITH STROKE
"\xC6\xB6" => 'z', // LATIN SMALL LETTER Z WITH STROKE
"\xC7\x8D" => 'A', // LATIN CAPITAL LETTER A WITH CARON
"\xC7\x8E" => 'a', // LATIN SMALL LETTER A WITH CARON
"\xC7\x8F" => 'I', // LATIN CAPITAL LETTER I WITH CARON
"\xC7\x90" => 'i', // LATIN SMALL LETTER I WITH CARON
"\xC7\x91" => 'O', // LATIN CAPITAL LETTER O WITH CARON
"\xC7\x92" => 'o', // LATIN SMALL LETTER O WITH CARON
"\xC7\x93" => 'U', // LATIN CAPITAL LETTER U WITH CARON
"\xC7\x94" => 'u', // LATIN SMALL LETTER U WITH CARON
"\xC7\x95" => 'U', // LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON
"\xC7\x96" => 'u', // LATIN SMALL LETTER U WITH DIAERESIS AND MACRON
"\xC7\x97" => 'U', // LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE
"\xC7\x98" => 'u', // LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE
"\xC7\x99" => 'U', // LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON
"\xC7\x9A" => 'u', // LATIN SMALL LETTER U WITH DIAERESIS AND CARON
"\xC7\x9B" => 'U', // LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE
"\xC7\x9C" => 'u', // LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE
"\xC7\x9E" => 'A', // LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON
"\xC7\x9F" => 'a', // LATIN SMALL LETTER A WITH DIAERESIS AND MACRON
"\xC7\xA0" => 'A', // LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON
"\xC7\xA1" => 'a', // LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON
"\xC7\xA2" => 'AE', // LATIN CAPITAL LETTER AE WITH MACRON
"\xC7\xA3" => 'ae', // LATIN SMALL LETTER AE WITH MACRON
"\xC7\xA4" => 'G', // LATIN CAPITAL LETTER G WITH STROKE
"\xC7\xA5" => 'g', // LATIN SMALL LETTER G WITH STROKE
"\xC7\xA6" => 'G', // LATIN CAPITAL LETTER G WITH CARON
"\xC7\xA7" => 'g', // LATIN SMALL LETTER G WITH CARON
"\xC7\xA8" => 'K', // LATIN CAPITAL LETTER K WITH CARON
"\xC7\xA9" => 'k', // LATIN SMALL LETTER K WITH CARON
"\xC7\xAA" => 'O', // LATIN CAPITAL LETTER O WITH OGONEK
"\xC7\xAB" => 'o', // LATIN SMALL LETTER O WITH OGONEK
"\xC7\xAC" => 'O', // LATIN CAPITAL LETTER O WITH OGONEK AND MACRON
"\xC7\xAD" => 'o', // LATIN SMALL LETTER O WITH OGONEK AND MACRON
"\xC7\xB0" => 'j', // LATIN SMALL LETTER J WITH CARON
"\xC7\xB4" => 'G', // LATIN CAPITAL LETTER G WITH ACUTE
"\xC7\xB5" => 'g', // LATIN SMALL LETTER G WITH ACUTE
"\xC7\xB8" => 'N', // LATIN CAPITAL LETTER N WITH GRAVE
"\xC7\xB9" => 'n', // LATIN SMALL LETTER N WITH GRAVE
"\xC7\xBA" => 'A', // LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE
"\xC7\xBB" => 'a', // LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE
"\xC7\xBC" => 'AE', // LATIN CAPITAL LETTER AE WITH ACUTE
"\xC7\xBD" => 'ae', // LATIN SMALL LETTER AE WITH ACUTE
"\xC7\xBE" => 'O', // LATIN CAPITAL LETTER O WITH STROKE AND ACUTE
"\xC7\xBF" => 'o', // LATIN SMALL LETTER O WITH STROKE AND ACUTE
"\xC8\x80" => 'A', // LATIN CAPITAL LETTER A WITH DOUBLE GRAVE
"\xC8\x81" => 'a', // LATIN SMALL LETTER A WITH DOUBLE GRAVE
"\xC8\x82" => 'A', // LATIN CAPITAL LETTER A WITH INVERTED BREVE
"\xC8\x83" => 'a', // LATIN SMALL LETTER A WITH INVERTED BREVE
"\xC8\x84" => 'E', // LATIN CAPITAL LETTER E WITH DOUBLE GRAVE
"\xC8\x85" => 'e', // LATIN SMALL LETTER E WITH DOUBLE GRAVE
"\xC8\x86" => 'E', // LATIN CAPITAL LETTER E WITH INVERTED BREVE
"\xC8\x87" => 'e', // LATIN SMALL LETTER E WITH INVERTED BREVE
"\xC8\x88" => 'I', // LATIN CAPITAL LETTER I WITH DOUBLE GRAVE
"\xC8\x89" => 'i', // LATIN SMALL LETTER I WITH DOUBLE GRAVE
"\xC8\x8A" => 'I', // LATIN CAPITAL LETTER I WITH INVERTED BREVE
"\xC8\x8B" => 'i', // LATIN SMALL LETTER I WITH INVERTED BREVE
"\xC8\x8C" => 'O', // LATIN CAPITAL LETTER O WITH DOUBLE GRAVE
"\xC8\x8D" => 'o', // LATIN SMALL LETTER O WITH DOUBLE GRAVE
"\xC8\x8E" => 'O', // LATIN CAPITAL LETTER O WITH INVERTED BREVE
"\xC8\x8F" => 'o', // LATIN SMALL LETTER O WITH INVERTED BREVE
"\xC8\x90" => 'R', // LATIN CAPITAL LETTER R WITH DOUBLE GRAVE
"\xC8\x91" => 'r', // LATIN SMALL LETTER R WITH DOUBLE GRAVE
"\xC8\x92" => 'R', // LATIN CAPITAL LETTER R WITH INVERTED BREVE
"\xC8\x93" => 'r', // LATIN SMALL LETTER R WITH INVERTED BREVE
"\xC8\x94" => 'U', // LATIN CAPITAL LETTER U WITH DOUBLE GRAVE
"\xC8\x95" => 'u', // LATIN SMALL LETTER U WITH DOUBLE GRAVE
"\xC8\x96" => 'U', // LATIN CAPITAL LETTER U WITH INVERTED BREVE
"\xC8\x97" => 'u', // LATIN SMALL LETTER U WITH INVERTED BREVE
"\xC8\x98" => 'S', // LATIN CAPITAL LETTER S WITH COMMA BELOW
"\xC8\x99" => 's', // LATIN SMALL LETTER S WITH COMMA BELOW
"\xC8\x9A" => 'T', // LATIN CAPITAL LETTER T WITH COMMA BELOW
"\xC8\x9B" => 't', // LATIN SMALL LETTER T WITH COMMA BELOW
"\xC8\x9E" => 'H', // LATIN CAPITAL LETTER H WITH CARON
"\xC8\x9F" => 'h', // LATIN SMALL LETTER H WITH CARON
"\xC8\xA0" => 'n', // LATIN CAPITAL LETTER N WITH LONG RIGHT LEG
"\xC8\xA1" => 'd', // LATIN SMALL LETTER D WITH CURL
"\xC8\xA4" => 'Z', // LATIN CAPITAL LETTER Z WITH HOOK
"\xC8\xA5" => 'z', // LATIN SMALL LETTER Z WITH HOOK
"\xC8\xA6" => 'A', // LATIN CAPITAL LETTER A WITH DOT ABOVE
"\xC8\xA7" => 'a', // LATIN SMALL LETTER A WITH DOT ABOVE
"\xC8\xA8" => 'E', // LATIN CAPITAL LETTER E WITH CEDILLA
"\xC8\xA9" => 'e', // LATIN SMALL LETTER E WITH CEDILLA
"\xC8\xAA" => 'O', // LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON
"\xC8\xAB" => 'o', // LATIN SMALL LETTER O WITH DIAERESIS AND MACRON
"\xC8\xAC" => 'O', // LATIN CAPITAL LETTER O WITH TILDE AND MACRON
"\xC8\xAD" => 'o', // LATIN SMALL LETTER O WITH TILDE AND MACRON
"\xC8\xAE" => 'O', // LATIN CAPITAL LETTER O WITH DOT ABOVE
"\xC8\xAF" => 'o', // LATIN SMALL LETTER O WITH DOT ABOVE
"\xC8\xB0" => 'O', // LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON
"\xC8\xB1" => 'o', // LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON
"\xC8\xB2" => 'Y', // LATIN CAPITAL LETTER Y WITH MACRON
"\xC8\xB3" => 'y', // LATIN SMALL LETTER Y WITH MACRON
"\xC8\xB4" => 'l', // LATIN SMALL LETTER L WITH CURL
"\xC8\xB5" => 'n', // LATIN SMALL LETTER N WITH CURL
"\xC8\xB6" => 't', // LATIN SMALL LETTER T WITH CURL
"\xC8\xB7" => 'j', // LATIN SMALL LETTER DOTLESS J
);
/**
* Return the UTF-8 input string converted into an array of words, changed $tolowercase (or not).
*
* Set $delimiters to true to keep the delimiters after each word and tweak what we used for word
* splitting with $splitideographs and $splithyphens.
*/
public static function stringToWords($string, $tolowercase=true, $delimiters=false, $splitideographs=true, $splithyphens=true)
{
if ($tolowercase)
$string = self::strtolower($string);
$string = strtr($string, self::$utf8Punctuation);
$separator = self::$pregIndexWordSeparator;
if ($splithyphens)
$separator .= '|\-';
if ($delimiters) {
if ($splitideographs)
$separator .= '|' . self::$pregCjkIdeographsUtf8;
}
else {
// remove apostrophes in words
$string = preg_replace("/(\S)'(\S)/", '\1\2', $string);
// put spaces around CJK ideographs so they're treated as separate words
if ($splitideographs)
$string = preg_replace('/'.self::$pregCjkIdeographsUtf8.'/', ' \0 ', $string);
}
return preg_split('/('.$separator.'+)/', $string, -1, PREG_SPLIT_NO_EMPTY | ($delimiters ? PREG_SPLIT_DELIM_CAPTURE : 0));
}
/**
* Return UTF-8 input $string with all accents (on Roman characters) removed
*/
public static function removeAccents($string)
{
return strtr($string, self::$utf8RemoveAccents);
}
/**
* Convert an array of tags into a string for storage in the database
*/
public static function tagsToTagstring($tags)
{
return implode(',', $tags);
}
/**
* Convert a tag string as stored in the database into an array of tags
*/
public static function tagstringToTags($tagstring)
{
return empty($tagstring) ? array() : explode(',', $tagstring);
}
/**
* Return no more than $length characters from $string after converting it to a single line, by
* removing words from the middle (and especially towards the end)
*/
public static function shortenStringLine($string, $length)
{
$string = strtr($string, "\r\n\t", ' ');
if (self::strlen($string) > $length) {
$remaining = $length - 5;
$words = self::stringToWords($string, false, true);
$countwords = count($words);
$prefix = '';
$suffix = '';
for ($addword = 0; $addword < $countwords; $addword++) {
$tosuffix = ($addword%3) == 1; // order: prefix, suffix, prefix, prefix, suffix, prefix, ...
if ($tosuffix)
$word = array_pop($words);
else
$word = array_shift($words);
if (self::strlen($word) > $remaining)
break;
if ($tosuffix)
$suffix = $word.$suffix;
else
$prefix .= $word;
$remaining -= self::strlen($word);
}
$string = $prefix.' ... '.$suffix;
}
return $string;
}
/**
* Return an array of the words within $wordstring, each of which can contain asterisks
*/
public static function blockWordsExplode($wordstring)
{
return preg_split('/'.self::$pregBlockWordSeparator.'+/', $wordstring, -1, PREG_SPLIT_NO_EMPTY);
}
/**
* Return a regular expression fragment corresponding to the block words $wordstring
*/
public static function blockWordsToPreg($wordsstring)
{
$blockwords = self::blockWordsExplode($wordsstring);
$patterns = array();
foreach ($blockwords as $blockword) {
// * in rule maps to [^ ]* in regular expression
$pattern = str_replace('\\*', '[^ ]*', preg_quote(self::strtolower($blockword), '/'));
// assert leading word delimiter if pattern does not start with CJK
if (!preg_match('/^('.self::$pregCjkIdeographsUtf8.')/', $blockword))
$pattern = '(?<= )' . $pattern;
// assert trailing word delimiter if pattern does not end with CJK
if (!preg_match('/('.self::$pregCjkIdeographsUtf8.')$/', $blockword))
$pattern = $pattern . '(?= )';
$patterns[] = $pattern;
}
return implode('|', $patterns);
}
/**
*Return an array of matches of the regular expression fragment $wordspreg in $string, [offset] => [length]
*/
public static function blockWordsMatchAll($string, $wordspreg)
{
if (strlen($wordspreg)) {
// replace all word separators with spaces of same length
if (empty(self::$utf8PunctuationKeepLength)) {
foreach (self::$utf8Punctuation as $key=>$value)
self::$utf8PunctuationKeepLength[$key] = str_repeat(' ', strlen($key));
}
// assumes UTF-8 case conversion in self::strtolower does not change byte length
$string = strtr(self::strtolower($string), self::$utf8PunctuationKeepLength);
$string = preg_replace('/'.self::$pregBlockWordSeparator.'/', ' ', $string);
preg_match_all('/'.$wordspreg.'/', ' '.$string.' ', $pregmatches, PREG_OFFSET_CAPTURE);
$outmatches = array();
foreach ($pregmatches[0] as $pregmatch)
$outmatches[$pregmatch[1]-1] = strlen($pregmatch[0]);
return $outmatches;
}
return array();
}
/**
* Return $string with any words matching the regular expression fragment $wordspreg replaced with repeated $character
*/
public static function blockWordsReplace($string, $wordspreg, $character='*')
{
if (strlen($wordspreg)) {
$matches = self::blockWordsMatchAll($string, $wordspreg);
krsort($matches, SORT_NUMERIC);
// get length again below to deal with multi-byte characters
foreach ($matches as $start => $length)
$string = substr_replace($string, str_repeat($character, self::strlen(substr($string, $start, $length))), $start, $length);
}
return $string;
}
/**
* Return a random alphanumeric string (base 36) of $length
*/
public static function randomAlphanum($length)
{
$string = '';
while (strlen($string) < $length)
$string .= str_pad(base_convert(mt_rand(0, 46655), 10, 36), 3, '0', STR_PAD_LEFT);
return substr($string, 0, $length);
}
/**
* Return true or false to indicate whether $email is a valid email (this is pretty flexible compared to most real emails out there)
*/
public static function emailValidate($email)
{
return preg_match("/^[\-\!\#\$\%\&\'\*\+\/\=\?\_\`\{\|\}\~a-zA-Z0-9\.\^]+\@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\.\-]+$/", $email) === 1;
}
/**
* Return the number of characters in $string, preferably using PHP's multibyte string functions
*/
public static function strlen($string)
{
return function_exists('mb_strlen') ? mb_strlen($string, 'UTF-8') : strlen($string);
}
/**
* Return a lower case version of $string, preferably using PHP's multibyte string functions
*/
public static function strtolower($string)
{
return function_exists('mb_strtolower') ? mb_strtolower($string, 'UTF-8') : strtolower($string);
}
/**
* Return $length characters from $string, starting from $start, preferably using PHP's multibyte string functions
*/
public static function substr($string, $start, $length=2147483647)
{
return function_exists('mb_substr') ? mb_substr($string, $start, $length, 'UTF-8') : substr($string, $start, $length);
}
/**
* Return whether this version of PHP has been compiled with multibyte string support
*/
public static function hasMultibyte()
{
return function_exists('mb_strlen') && function_exists('mb_strtolower');
}
/**
* Return true if one of the elements in $matches is contained within $string
*/
public static function stringMatchesOne($string, $matches)
{
if (strlen($string)) {
foreach ($matches as $match) {
if (strpos($string, $match) !== false)
return true;
}
}
return false;
}
}
<?php
/*
Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/
License: GPLv2+ <http://www.question2answer.org/license.php>
File: qa-include/qa-util-debug.php
Description: Debugging stuff, currently used for tracking resource usage
*/
class Q2A_Util_Usage
{
public $database_usage;
public $database_queries;
public $usage_start;
public $usage_last;
/**
* Initialize the counts of resource usage
*/
public function __construct()
{
global $qa_database_usage, $qa_database_queries, $qa_usage_start, $qa_usage_last;
$qa_database_usage = array('queries'=>0, 'clock'=>0);
$qa_database_queries = '';
$qa_usage_last = $qa_usage_start = $this->getCurrent();
}
/**
* Return an array representing the resource usage as of now
*/
public function getCurrent()
{
global $qa_database_usage;
$usage = array(
'files' => count(get_included_files()),
'queries' => $qa_database_usage['queries'],
'ram' => function_exists('memory_get_usage') ? memory_get_usage() : 0,
'clock' => array_sum(explode(' ', microtime())),
'mysql' => $qa_database_usage['clock'],
);
if (function_exists('getrusage')) {
$rusage = getrusage();
$usage['cpu'] = $rusage["ru_utime.tv_sec"] + $rusage["ru_stime.tv_sec"]
+ ($rusage["ru_utime.tv_usec"] + $rusage["ru_stime.tv_usec"]) / 1000000;
}
else
$usage['cpu'] = 0;
$usage['other'] = $usage['clock'] - $usage['cpu'] - $usage['mysql'];
return $usage;
}
/**
* Mark the beginning of a new stage of script execution and store usages accordingly
*/
public function mark($stage)
{
global $qa_usage_last, $qa_usage_stages;
$usage = $this->getCurrent();
$qa_usage_stages[$stage] = $this->delta($qa_usage_last, $usage);
$qa_usage_last = $usage;
}
/**
* Output an (ugly) block of HTML detailing all resource usage and database queries
*/
public function output()
{
global $qa_usage_start, $qa_usage_stages, $qa_database_queries;
$totaldelta = $this->delta($qa_usage_start, $this->getCurrent());
?>
<style>
.debug-table { border-collapse: collapse; box-sizing: border-box; width: 100%; margin: 20px auto; }
.debug-table tr { background-color: #ccc; }
.debug-table td { padding: 10px; }
td.debug-cell-files { width: 30%; padding-right: 5px; }
td.debug-cell-queries { width: 70%; padding-left: 5px; }
textarea.debug-output { box-sizing: border-box; width: 100%; font: 12px monospace; color: #000; }
</style>
<table class="debug-table">
<tbody>
<tr>
<td colspan="2"><?php
echo $this->line('Total', $totaldelta, $totaldelta) . "<br>\n";
foreach ($qa_usage_stages as $stage => $stagedelta)
echo '<br>' . $this->line(ucfirst($stage), $stagedelta, $totaldelta) . "\n";
?></td>
</tr>
<tr>
<td class="debug-cell-files">
<textarea class="debug-output" cols="40" rows="20"><?php
foreach (get_included_files() as $file)
echo qa_html(implode('/', array_slice(explode('/', $file), -3)))."\n";
?></textarea>
</td>
<td class="debug-cell-queries">
<textarea class="debug-output" cols="40" rows="20"><?=qa_html($qa_database_queries)?></textarea>
</td>
</tr>
</tbody>
</table>
<?php
}
/**
* Return the difference between two resource usage arrays, as an array
*/
private function delta($oldusage, $newusage)
{
$delta = array();
foreach ($newusage as $key => $value)
$delta[$key] = max(0, $value-@$oldusage[$key]);
return $delta;
}
/**
* Return HTML to represent the resource $usage, showing appropriate proportions of $totalusage
*/
private function line($stage, $usage, $totalusage)
{
return sprintf(
"%s &ndash; <b>%.1fms</b> (%d%%) &ndash; PHP %.1fms (%d%%), MySQL %.1fms (%d%%), Other %.1fms (%d%%) &ndash; %d PHP %s, %d DB %s, %dk RAM (%d%%)",
$stage,
$usage['clock'] * 1000,
$usage['clock'] * 100 / $totalusage['clock'],
$usage['cpu'] * 1000,
$usage['cpu'] * 100 / $totalusage['clock'],
$usage['mysql'] * 1000,
$usage['mysql'] * 100 / $totalusage['clock'],
$usage['other'] * 1000,
$usage['other'] * 100 / $totalusage['clock'],
$usage['files'],
$usage['files'] == 1 ? 'file' : 'files',
$usage['queries'],
$usage['queries'] == 1 ? 'query' : 'queries',
$usage['ram'] / 1024,
$usage['ram'] ? ($usage['ram'] * 100 / $totalusage['ram']) : 0
);
}
}
......@@ -196,8 +196,8 @@
// Start performance monitoring
if (QA_DEBUG_PERFORMANCE) {
require_once 'qa-util-debug.php';
qa_usage_init();
global $qa_usage;
$qa_usage = new Q2A_Util_Usage;
}
// More for WordPress integration
......
......@@ -465,8 +465,10 @@
global $qa_template, $qa_page_error_html;
if (QA_DEBUG_PERFORMANCE)
qa_usage_mark('control');
if (QA_DEBUG_PERFORMANCE) {
global $qa_usage;
$qa_usage->mark('control');
}
$request=qa_request();
$requestlower=qa_request();
......@@ -779,6 +781,8 @@
// Below are the steps that actually execute for this file - all the above are function definitions
global $qa_usage;
qa_report_process_stage('init_page');
qa_db_connect('qa_page_db_fail_handler');
......@@ -787,27 +791,26 @@
qa_check_login_modules();
if (QA_DEBUG_PERFORMANCE)
qa_usage_mark('setup');
$qa_usage->mark('setup');
qa_check_page_clicks();
$qa_content=qa_get_request_content();
$qa_content = qa_get_request_content();
if (is_array($qa_content)) {
if (QA_DEBUG_PERFORMANCE)
qa_usage_mark('view');
$qa_usage->mark('view');
qa_output_content($qa_content);
if (QA_DEBUG_PERFORMANCE)
qa_usage_mark('theme');
$qa_usage->mark('theme');
if (qa_do_content_stats($qa_content))
if (QA_DEBUG_PERFORMANCE)
qa_usage_mark('stats');
if (qa_do_content_stats($qa_content) && QA_DEBUG_PERFORMANCE)
$qa_usage->mark('stats');
if (QA_DEBUG_PERFORMANCE)
qa_usage_output();
$qa_usage->output();
}
qa_db_disconnect();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment