From e8312985a2525078957d8f540ad4bc53938c9b94 Mon Sep 17 00:00:00 2001 From: kjmtsh Date: Sun, 7 Jul 2013 06:49:38 +0000 Subject: [PATCH] first release git-svn-id: https://plugins.svn.wordpress.org/sqlite-integration/trunk@737264 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- db.php | 96 +++ functions-5-2.php | 370 +++++++++ functions.php | 344 ++++++++ install.php | 63 ++ js/sqlite.js | 101 +++ languages/sqlite-integration-ja.mo | Bin 0 -> 43052 bytes languages/sqlite-integration-ja.po | 1198 ++++++++++++++++++++++++++++ languages/sqlite-integration.pot | 1057 ++++++++++++++++++++++++ pdodb.class.php | 240 ++++++ pdoengine.class.php | 898 +++++++++++++++++++++ query.class.php | 526 ++++++++++++ query_alter.class.php | 453 +++++++++++ query_create.class.php | 285 +++++++ readme-ja.txt | 170 ++++ readme.txt | 162 ++++ schema.php | 91 +++ screenshots-1.png | Bin 0 -> 89858 bytes sqlite-integration.php | 238 ++++++ styles/doc.css | 141 ++++ styles/style.css | 216 +++++ utilities/documentation.php | 193 +++++ utilities/patch.php | 340 ++++++++ utilities/plugin_lists.json | 313 ++++++++ utilities/utility.php | 679 ++++++++++++++++ 24 files changed, 8174 insertions(+) create mode 100644 db.php create mode 100644 functions-5-2.php create mode 100644 functions.php create mode 100644 install.php create mode 100644 js/sqlite.js create mode 100644 languages/sqlite-integration-ja.mo create mode 100644 languages/sqlite-integration-ja.po create mode 100644 languages/sqlite-integration.pot create mode 100644 pdodb.class.php create mode 100644 pdoengine.class.php create mode 100644 query.class.php create mode 100644 query_alter.class.php create mode 100644 query_create.class.php create mode 100644 readme-ja.txt create mode 100644 readme.txt create mode 100644 schema.php create mode 100644 screenshots-1.png create mode 100644 sqlite-integration.php create mode 100644 styles/doc.css create mode 100644 styles/style.css create mode 100644 utilities/documentation.php create mode 100644 utilities/patch.php create mode 100644 utilities/plugin_lists.json create mode 100644 utilities/utility.php diff --git a/db.php b/db.php new file mode 100644 index 0000000..d108dfc --- /dev/null +++ b/db.php @@ -0,0 +1,96 @@ + + + + WordPress › Error + + + + +

WordPress

+

$message

+

$data

+ + + +HTML +); +} + +if (version_compare( PHP_VERSION, '5.2.4', '<')) { + pdo_log_erro(__('PHP version on this server is too old.'), sprinf(__("Your server is running PHP version %d but this version of WordPress requires at least 5.2.4"), phpversion())); +} + +if (!extension_loaded('pdo')) { + pdo_log_erro(__('PHP PDO Extension is not loaded.'), __('Your PHP installation appears to be missing the PDO extension which is required for this version of WordPress.')); +} + +if (!extension_loaded('pdo_sqlite')) { + pdo_log_erro(__('PDO Driver for SQLite is missing.'), __('Your PHP installtion appears not to have the right PDO drivers loaded. These are required for this version of WordPress and the type of database you have specified.')); +} + +/** + * Notice: + * Your scripts have the permission to create directories or files on your server. + * If you write in your wp-config.php like below, we take these definitions. + * define('DB_DIR', '/full_path_to_the_database_directory/'); + * define('DB_FILE', 'database_file_name'); + */ +if (defined('WP_PLUGIN_DIR')) { + define('PDODIR', WP_PLUGIN_DIR . '/sqlite-integration/'); +} else { + if (defined('WP_CONTENT_DIR')) { + define('PDODIR', WP_CONTENT_DIR . '/plugins/sqlite-integration/'); + } else { + define('PDODIR', ABSPATH . 'wp-content/plugins/sqlite-integration/'); + } +} + +if (defined('DB_DIR')) { + if (substr(DB_DIR, -1, 1) != '/') { + define('FQDBDIR', DB_DIR . '/'); + } else { + define('FQDBDIR', DB_DIR); + } +} else { + if (defined('WP_CONTENT_DIR')) { + define('FQDBDIR', WP_CONTENT_DIR . '/database/'); + } else { + define('FQDBDIR', ABSPATH . 'wp-content/database/'); + } +} + +if ( defined('DB_FILE' )) { + define('FQDB', FQDBDIR . DB_FILE); +} else { + define('FQDB', FQDBDIR . '.ht.sqlite'); +} + +if (version_compare(PHP_VERSION, '5.3', '<')) { + define('UDF_FILE', PDODIR . 'functions-5-2.php'); +} elseif (version_compare(PHP_VERSION, '5.3', '>=')) { + define('UDF_FILE', PDODIR . 'functions.php'); +} + +require_once PDODIR . 'pdodb.class.php'; +?> \ No newline at end of file diff --git a/functions-5-2.php b/functions-5-2.php new file mode 100644 index 0000000..545b653 --- /dev/null +++ b/functions-5-2.php @@ -0,0 +1,370 @@ +functions as $f=>$t) { + $pdo->sqliteCreateFunction($f, array($this, $t)); + } + } + + private $functions = array( + 'month' => 'month', + 'year' => 'year', + 'day' => 'day', + 'unix_timestamp' => 'unix_timestamp', + 'now' => 'now', + 'char_length' => 'char_length', + 'md5' => 'md5', + 'curdate' => 'curdate', + 'rand' => 'rand', + 'substring' => 'substring', + 'dayofmonth' => 'day', + 'second' => 'second', + 'minute' => 'minute', + 'hour' => 'hour', + 'date_format' => 'dateformat', + 'from_unixtime' => 'from_unixtime', + 'date_add' => 'date_add', + 'date_sub' => 'date_sub', + 'adddate' => 'date_add', + 'subdate' => 'date_sub', + 'localtime' => 'now', + 'localtimestamp' => 'now', + //'date'=>'date', + 'isnull' => 'isnull', + 'if' => '_if', + 'regexpp' => 'regexp', + 'concat' => 'concat', + 'field' => 'field', + 'log' => 'log', + 'least' => 'least', + 'get_lock' => 'get_lock', + 'release_lock' => 'release_lock', + 'ucase' => 'ucase', + 'lcase' => 'lcase', + 'inet_ntoa' => 'inet_ntoa', + 'inet_aton' => 'inet_aton', + 'datediff' => 'datediff' + ); + + public function month($field){ + $t = strtotime($field); + return date('n', $t); + } + public function year($field){ + $t = strtotime($field); + return date('Y', $t); + } + public function day($field){ + $t = strtotime($field); + return date('j', $t); + } + public function unix_timestamp($field = null){ + return is_null($field) ? time() : strtotime($field); + } + public function second($field){ + $t = strtotime($field); + return intval( date("s", $t) ); + } + public function minute($field){ + $t = strtotime($field); + return intval(date("i", $t)); + } + public function hour($time){ + list($hours, $minutes, $seconds) = explode(":", $time); + return intval($hours); + } + public function from_unixtime($field, $format=null){ + // $field is a timestamp + //convert to ISO time + $date = date("Y-m-d H:i:s", $field); + //now submit to dateformat + + return is_null($format) ? $date : $self->dateformat($date, $format); + } + public function now(){ + return date("Y-m-d H:i:s"); + } + public function curdate() { + return date("Y-m-d"); + } + public function char_length($field){ + return strlen($field); + } + public function md5($field){ + return md5($field); + } + public function rand(){ + return rand(0,1); + } + public function substring($text, $pos, $len=null){ + if (is_null($len)) return substr($text, $pos-1); + else return substr($text, $pos-1, $len); + } + public function dateformat($date, $format){ + $mysql_php_dateformats = array ( '%a' => 'D', '%b' => 'M', '%c' => 'n', '%D' => 'jS', '%d' => 'd', '%e' => 'j', '%H' => 'H', '%h' => 'h', '%I' => 'h', '%i' => 'i', '%j' => 'z', '%k' => 'G', '%l' => 'g', '%M' => 'F', '%m' => 'm', '%p' => 'A', '%r' => 'h:i:s A', '%S' => 's', '%s' => 's', '%T' => 'H:i:s', '%U' => 'W', '%u' => 'W', '%V' => 'W', '%v' => 'W', '%W' => 'l', '%w' => 'w', '%X' => 'Y', '%x' => 'o', '%Y' => 'Y', '%y' => 'y', ); + $t = strtotime($date); + $format = strtr($format, $mysql_php_dateformats); + $output = date($format, $t); + return $output; + } + public function date_add($date, $interval) { + $interval = $this->deriveInterval($interval); + switch (strtolower($date)) { + case "curdate()": + $objDate = new Datetime($this->curdate()); + $objDate->add(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d"); + break; + case "now()": + $objDate = new Datetime($this->now()); + $objDate->add(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d H:i:s"); + break; + default: + $objDate = new Datetime($date); + $objDate->add(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d H:i:s"); + } + return $returnval; + } + public function date_sub($date, $interval) { + $interval = $this->deriveInterval($interval); + switch (strtolower($date)) { + case "curdate()": + $objDate = new Datetime($this->curdate()); + $objDate->sub(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d"); + break; + case "now()": + $objDate = new Datetime($this->now()); + $objDate->sub(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d H:i:s"); + break; + default: + $objDate = new Datetime($date); + $objDate->sub(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d H:i:s"); + } + return $returnval; + } + + private function deriveInterval($interval){ + $interval = trim(substr(trim($interval), 8)); + $parts = explode(' ', $interval); + foreach($parts as $part){ + if (!empty($part)){ + $_parts[] = $part; + } + } + $type = strtolower(end($_parts)); + switch ($type){ + case "second": + case "minute": + case "hour": + case "day": + case "week": + case "month": + case "year": + if (intval($_parts[0]) > 1){ + $type .= 's'; + } + return "$_parts[0] $_parts[1]"; + break; + case "minute_second": + list($minutes, $seconds) = explode (':', $_parts[0]); + $minutes = intval($minutes); + $seconds = intval($seconds); + $minutes = ($minutes > 1) ? "$minutes minutes" : "$minutes minute"; + $seconds = ($seconds > 1) ? "$seconds seconds" : "$seconds second"; + return "$minutes $seconds"; + break; + + case "hour_second": + list($hours, $minutes, $seconds) = explode (':', $_parts[0]); + $hours = intval($hours); + $minutes = intval($minutes); + $seconds = intval($seconds); + $hours = ($hours > 1) ? "$hours hours" : "$hours hour"; + $minutes = ($minutes > 1) ? "$minutes minutes" : "$minutes minute"; + $seconds = ($seconds > 1) ? "$seconds seconds" : "$seconds second"; + return "$hours $minutes $seconds"; + break; + case "hour_minute": + list($hours, $minutes) = explode (':', $_parts[0]); + $hours = intval($hours); + $minutes = intval($minutes); + $hours = ($hours > 1) ? "$hours hours" : "$hours hour"; + $minutes = ($minutes > 1) ? "$minutes minutes" : "$minutes minute"; + return "$hours $minutes"; + break; + case "day_second": + $days = intval($_parts[0]); + list($hours, $minutes, $seconds) = explode (':', $_parts[1]); + $hours = intval($hours); + $minutes = intval($minutes); + $seconds = intval($seconds); + $days = $days > 1 ? "$days days" : "$days day"; + $hours = ($hours > 1) ? "$hours hours" : "$hours hour"; + $minutes = ($minutes > 1) ? "$minutes minutes" : "$minutes minute"; + $seconds = ($seconds > 1) ? "$seconds seconds" : "$seconds second"; + return "$days $hours $minutes $seconds"; + break; + case "day_minute": + $days = intval($_parts[0]); + list($hours, $minutes) = explode (':', $_parts[1]); + $hours = intval($hours); + $minutes = intval($minutes); + $days = $days > 1 ? "$days days" : "$days day"; + $hours = ($hours > 1) ? "$hours hours" : "$hours hour"; + $minutes = ($minutes > 1) ? "$minutes minutes" : "$minutes minute"; + return "$days $hours $minutes"; + break; + case "day_hour": + $days = intval($_parts[0]); + $hours = intval($_parts[1]); + $days = $days > 1 ? "$days days" : "$days day"; + $hours = ($hours > 1) ? "$hours hours" : "$hours hour"; + return "$days $hours"; + break; + case "year_month": + list($years, $months) = explode ('-', $_parts[0]); + $years = intval($years); + $months = intval($months); + $years = ($years > 1) ? "$years years" : "$years year"; + $months = ($months > 1) ? "$months months": "$months month"; + return "$years $months"; + break; + default: + return false; + } + } + + public function date($date){ + return date("Y-m-d", strtotime($date)); + } + + public function isnull($field){ + return is_null($field); + } + + public function _if($expression, $true, $false){ + return ($expression == true) ? $true : $false; + } + + public function regexp($field, $pattern){ + $pattern = str_replace('/', '\/', $pattern); + $pattern = "/" . $pattern ."/i"; + return preg_match ($pattern, $field); + } + + public function concat() { + $returnValue = ""; + $argsNum = func_num_args(); + $argsList = func_get_args(); + for ($i = 0; $i < $argsNum; $i++) { + if (is_null($argsList[$i])) { + return null; + } + $returnValue .= $argsList[$i]; + } + return $returnValue; + } + + public function field() { + $numArgs = func_num_args(); + if ($numArgs < 2 or is_null(func_get_arg(0))) { + return null; + } + $arr = func_get_args(); + $searchString = strtolower(array_shift($arr)); + for ($i = 0; $i < $numArgs-1; $i++) { + if ($searchString === strtolower($arr[$i])) return $i + 1; + } + return null; + } + + public function log() { + $numArgs = func_num_args(); + if ($numArgs == 1) { + $arg1 = func_get_arg(0); + return log($arg1); + } else if ($numArgs == 2) { + $arg1 = func_get_arg(0); + $arg2 = func_get_arg(1); + return log($arg1)/log($arg2); + } else { + return false; + } + } + + public function least() { + $arr = func_get_args(); + return min($arr); + } + + /** + * These two functions are meaningless in SQLite + * So we return meaningless statement and do nothing + * @param string $name + * @param integer $timeout + * @return string + */ + public function get_lock($name, $timeout) { + return '1=1'; + } + public function release_lock($name) { + return '1=1'; + } + + /** + * MySQL aliases for upper and lower functions + * @param unknown $string + * @return string + */ + public function ucase($string) { + return "upper($string)"; + } + public function lcase($string) { + return "lower($string)"; + } + + /** + * MySQL aliases for INET_NTOA and INET_ATON functions + * @param unsigned integer, string respectively + * @return string, unsigned integer respectively + */ + public function inet_ntoa($num) { + return long2ip($num); + } + public function inet_aton($addr) { + $int_data = ip2long($addr); + $unsigned_int_data = sprintf('%u', $address); + return $unsigned_int_data; + } + + /** + * MySQL aliase for DATEDIFF function + * @param string, string + * @return string + */ + public function datediff($start, $end) { + $start_date = strtotime($start); + $end_date = strtotime($end); + $interval = floor(($end_date - $start_date)/(3600*24)); + return $interval; + } +} +?> \ No newline at end of file diff --git a/functions.php b/functions.php new file mode 100644 index 0000000..5f7af23 --- /dev/null +++ b/functions.php @@ -0,0 +1,344 @@ +functions as $f=>$t) { + $pdo->sqliteCreateFunction($f, array($this, $t)); + } + } + + private $functions = array( + 'month' => 'month', + 'year' => 'year', + 'day' => 'day', + 'unix_timestamp' => 'unix_timestamp', + 'now' => 'now', + 'char_length' => 'char_length', + 'md5' => 'md5', + 'curdate' => 'curdate', + 'rand' => 'rand', + 'substring' => 'substring', + 'dayofmonth' => 'day', + 'second' => 'second', + 'minute' => 'minute', + 'hour' => 'hour', + 'date_format' => 'dateformat', + 'from_unixtime' => 'from_unixtime', + 'date_add' => 'date_add', + 'date_sub' => 'date_sub', + 'adddate' => 'date_add', + 'subdate' => 'date_sub', + 'localtime' => 'now', + 'localtimestamp' => 'now', + //'date'=>'date', + 'isnull' => 'isnull', + 'if' => '_if', + 'regexpp' => 'regexp', + 'concat' => 'concat', + 'field' => 'field', + 'log' => 'log', + 'least' => 'least', + 'replace' => 'replace', + 'get_lock' => 'get_lock', + 'release_lock' => 'release_lock', + 'ucase' => 'ucase', + 'lcase' => 'lcase', + 'inet_ntoa' => 'inet_ntoa', + 'inet_aton' => 'inet_aton', + 'datediff' => 'datediff' + ); + + public function month($field){ + $t = strtotime($field); + return date('n', $t); + } + public function year($field){ + $t = strtotime($field); + return date('Y', $t); + } + public function day($field){ + $t = strtotime($field); + return date('j', $t); + } + public function unix_timestamp($field = null){ + return is_null($field) ? time() : strtotime($field); + } + public function second($field){ + $t = strtotime($field); + return intval( date("s", $t) ); + } + public function minute($field){ + $t = strtotime($field); + return intval(date("i", $t)); + } + public function hour($time){ + list($hours, $minutes, $seconds) = explode(":", $time); + return intval($hours); + } + public function from_unixtime($field, $format=null){ + // $field is a timestamp + //convert to ISO time + $date = date("Y-m-d H:i:s", $field); + //now submit to dateformat + + return is_null($format) ? $date : $self->dateformat($date, $format); + } + public function now(){ + return date("Y-m-d H:i:s"); + } + public function curdate() { + return date("Y-m-d"); + } + public function char_length($field){ + return strlen($field); + } + public function md5($field){ + return md5($field); + } + public function rand(){ + return rand(0,1); + } + public function substring($text, $pos, $len=null){ + if (is_null($len)) return substr($text, $pos-1); + else return substr($text, $pos-1, $len); + } + public function dateformat($date, $format){ + $mysql_php_dateformats = array ( '%a' => 'D', '%b' => 'M', '%c' => 'n', '%D' => 'jS', '%d' => 'd', '%e' => 'j', '%H' => 'H', '%h' => 'h', '%I' => 'h', '%i' => 'i', '%j' => 'z', '%k' => 'G', '%l' => 'g', '%M' => 'F', '%m' => 'm', '%p' => 'A', '%r' => 'h:i:s A', '%S' => 's', '%s' => 's', '%T' => 'H:i:s', '%U' => 'W', '%u' => 'W', '%V' => 'W', '%v' => 'W', '%W' => 'l', '%w' => 'w', '%X' => 'Y', '%x' => 'o', '%Y' => 'Y', '%y' => 'y', ); + $t = strtotime($date); + $format = strtr($format, $mysql_php_dateformats); + $output = date($format, $t); + return $output; + } + public function date_add($date, $interval) { + $interval = $this->deriveInterval($interval); + switch (strtolower($date)) { + case "curdate()": + $objDate = new Datetime($this->curdate()); + $objDate->add(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d"); + break; + case "now()": + $objDate = new Datetime($this->now()); + $objDate->add(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d H:i:s"); + break; + default: + $objDate = new Datetime($date); + $objDate->add(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d H:i:s"); + } + return $returnval; + } + public function date_sub($date, $interval) { + $interval = $this->deriveInterval($interval); + switch (strtolower($date)) { + case "curdate()": + $objDate = new Datetime($this->curdate()); + $objDate->sub(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d"); + break; + case "now()": + $objDate = new Datetime($this->now()); + $objDate->sub(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d H:i:s"); + break; + default: + $objDate = new Datetime($date); + $objDate->sub(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d H:i:s"); + } + return $returnval; + } + private function deriveInterval($interval) { + $interval = trim(substr(trim($interval), 8)); + $parts = explode(' ', $interval); + foreach ($parts as $part) { + if (!empty($part)) { + $_parts[] = $part; + } + } + $type = strtolower(end($_parts)); + switch ($type) { + case "second": $unit = 'S'; return 'PT' . $_parts[0] . $unit; break; + case "minute": $unit = 'M'; return 'PT' . $_parts[0] . $unit; break; + case "hour": $unit = 'H'; return 'PT' . $_parts[0] . $unit; break; + case "day": $unit = 'D'; return 'P' . $_parts[0] . $unit; break; + case "week": $unit = 'W'; return 'P' . $_parts[0] . $unit; break; + case "month": $unit = 'M'; return 'P' . $_parts[0] . $unit; break; + case "year": $unit = 'Y'; return 'P' . $_parts[0] . $unit; break; + case "minute_second": + list($minutes, $seconds) = explode(':', $_parts[0]); + return 'PT' . $minutes . 'M' . $seconds . 'S'; + break; + case "hour_second": + list($hours, $minutes, $seconds) = explode (':', $_parts[0]); + return 'PT' . $hours . 'H' . $minutes . 'M' . $seconds . 'S'; + break; + case "hour_minute": + list($hours, $minutes) = explode (':', $_parts[0]); + return 'PT' . $hours . 'H' . $minutes . 'M'; + break; + case "day_second": + $days = intval($_parts[0]); + list($hours, $minutes, $seconds) = explode (':', $_parts[1]); + return 'P' . $days . 'D' . 'T' . $hours . 'H' . $minutes . 'M' . $seconds . 'S'; + break; + case "day_minute": + $days = intval($_parts[0]); + list($hours, $minutes) = explode(':', $parts[1]); + return 'P' . $days . 'D' . 'T' . $hours . 'H' . $minutes . 'M'; + break; + case "day_hour": + $days = intval($_parts[0]); + $hours = intval($_parts[1]); + return 'P' . $days . 'D' . 'T' . $hours . 'H'; + break; + case "year_month": + list($years, $months) = explode ('-', $_parts[0]); + return 'P' . $years . 'Y' . $months . 'M'; + break; + } + } + + public function date($date){ + return date("Y-m-d", strtotime($date)); + } + + public function isnull($field){ + return is_null($field); + } + + public function _if($expression, $true, $false){ + return ($expression == true) ? $true : $false; + } + + public function regexp($field, $pattern){ + $pattern = str_replace('/', '\/', $pattern); + $pattern = "/" . $pattern ."/i"; + return preg_match ($pattern, $field); + } + + public function concat() { + $returnValue = ""; + $argsNum = func_num_args(); + $argsList = func_get_args(); + for ($i = 0; $i < $argsNum; $i++) { + if (is_null($argsList[$i])) { + return null; + } + $returnValue .= $argsList[$i]; + } + return $returnValue; + } + + public function field() { + $numArgs = func_num_args(); + if ($numArgs < 2 or is_null(func_get_arg(0))) { + return null; + } + $arr = func_get_args(); + $searchString = strtolower(array_shift($arr)); + for ($i = 0; $i < $numArgs-1; $i++) { + if ($searchString === strtolower($arr[$i])) return $i + 1; + } + return null; + } + + public function log() { + $numArgs = func_num_args(); + if ($numArgs == 1) { + $arg1 = func_get_arg(0); + return log($arg1); + } else if ($numArgs == 2) { + $arg1 = func_get_arg(0); + $arg2 = func_get_arg(1); + return log($arg1)/log($arg2); + } else { + return false; + } + } + + public function least() { + $arr = func_get_args(); + return min($arr); + } + + public function replace($haystack, $needle, $replace) { + return str_replace($needle, $replace, $haystack); + } + + /** + * These two functions are meaningless in SQLite + * So we return meaningless statement and do nothing + * @param string $name + * @param integer $timeout + * @return string + */ + public function get_lock($name, $timeout) { + return '1=1'; + } + public function release_lock($name) { + return '1=1'; + } + + /** + * MySQL aliases for upper and lower functions + * @param $string + * @return string + */ + public function ucase($string) { + return "upper($string)"; + } + public function lcase($string) { + return "lower($string)"; + } + + /** + * MySQL aliases for INET_NTOA and INET_ATON functions + * @param unsigned integer, string respectively + * @return string, unsigned integer respectively + */ + public function inet_ntoa($num) { + return long2ip($num); + } + public function inet_aton($addr) { + $int_data = ip2long($addr); + $unsigned_int_data = sprintf('%u', $address); + return $unsigned_int_data; + } + + /** + * MySQL aliase for DATEDIFF function + * @param string, string + * @return string + */ + public function datediff($start, $end) { + /* PHP 5.3.2 has a serious bug in DateTime::diff() + * see https://bugs.php.net/bug.php?id=51184 + */ + if (version_compare(PHP_VERSION, '5.3.2', '==')) { + $start_date = strtotime($start); + $end_date = strtotime($end); + $interval = floor(($start_date - $end_date)/(3600*24)); + return $interval; + } else { + $start_date = new DateTime($start); + $end_date = new DateTime($end); + $interval = $end_date->diff($start_date, false); + return $interval->format('%r%a'); + } + } +} +?> \ No newline at end of file diff --git a/install.php b/install.php new file mode 100644 index 0000000..6a0dfe4 --- /dev/null +++ b/install.php @@ -0,0 +1,63 @@ +Note that password carefully! It is a random password that was generated just for you.'); + $user_id = wp_create_user($user_name, $user_password, $user_email); + update_user_option($user_id, 'default_password_nag', true, true); + $email_password = true; + } else if (!$user_id) { + $message = ''.__('Your chosen password.').''; + $user_id = wp_create_user($user_name, $user_password, $user_email); + } + + $user = new WP_User($user_id); + $user->set_role('administrator'); + + wp_install_defaults($user_id); + + flush_rewrite_rules(); + + wp_new_blog_notification($blog_title, $guessurl, $user_id, ($email_password ? $user_password : __('The password you chose during the install.'))); + + wp_cache_flush(); + + return array('url' => $guessurl, 'user_id' => $user_id, 'password' => $user_password, 'password_message' => $message); +} +?> \ No newline at end of file diff --git a/js/sqlite.js b/js/sqlite.js new file mode 100644 index 0000000..140eae7 --- /dev/null +++ b/js/sqlite.js @@ -0,0 +1,101 @@ +/* + * script for SQLite Integration + * this file is only included on the documentation page and the utilities page + */ +jQuery(document).ready(function($) { + var $table = null; + var $headers = null; + if (document.getElementById("sqlite-table") != null) { + $table = $('#sqlite-table'); + $headers = $table.find('thead th').slice(0,2); + } else if (document.getElementById("plugins-table") != null) { + $table = $('#plugins-table'); + $headers = $table.find('thead th').slice(0); + } else if (document.getElementById("patch-files") != null) { + $table = $('#patch-files'); + $headers = $table.find('thead th').slice(1); + } + $headers + .wrapInner('') + .addClass('sort'); + var rows = $table.find('tbody > tr').get(); + $headers.bind('click', function(event) { + event.preventDefault(); + var $header = $(this), + sortKey = $header.data('sort').key, + sortDirection = 1; + if ($header.hasClass('sorted-asc')) { + sortDirection = -1; + } + rows.sort(function(a, b) { + var keyA = $(a).data('table')[sortKey]; + var keyB = $(b).data('table')[sortKey]; + if (keyA < keyB) return -sortDirection; + if (keyA > keyB) return sortDirection; + return 0; + }); + $headers.removeClass('sorted-asc sortd-desc'); + $headers.addClass(sortDirection == 1 ? 'sorted-asc' : 'sorted-desc'); + $.each(rows, function(index, row) { + $table.children('tbody').append(row); + }); + stripe('#plugins-table'); + stripe('#sqlite-table'); + stripe('#patch-files'); + }); + function stripe(arg) { + $(arg).find('tr.alt').removeClass('alt'); + var $args = arg + ' tbody'; + $($args).each(function() { + $(this).children(':visible').has('td').filter(function(index) { + return (index % 2) == 1; + }).addClass('alt'); + }); + } + stripe('#plugins-table'); + stripe('#sys-info'); + stripe('#sqlite-table'); + stripe('#status'); + stripe('#patch-files'); +}); + +jQuery(document).ready(function($) { + var $table = $('#plugins-info'); + var $headers = $table.find('thead th').slice(0); + $headers + .wrapInner('') + .addClass('sort'); + var rows = $table.find('tbody > tr').get(); + $headers.bind('click', function(event) { + event.preventDefault(); + var $header = $(this), + sortKey = $header.data('sort').key, + sortDirection = 1; + if ($header.hasClass('sorted-asc')) { + sortDirection = -1; + } + rows.sort(function(a, b) { + var keyA = $(a).data('table')[sortKey]; + var keyB = $(b).data('table')[sortKey]; + if (keyA < keyB) return -sortDirection; + if (keyA > keyB) return sortDirection; + return 0; + }); + $headers.removeClass('sorted-asc sortd-desc'); + $headers.addClass(sortDirection == 1 ? 'sorted-asc' : 'sorted-desc'); + $.each(rows, function(index, row) { + $table.children('tbody').append(row); + }); + stripe('#plugins-info'); + }); + function stripe(arg) { + $(arg).find('tr.alt').removeClass('alt'); + var $args = arg + ' tbody'; + $($args).each(function() { + $(this).children(':visible').has('td').filter(function(index) { + return (index % 2) == 1; + }).addClass('alt'); + }); + } + stripe('#plugins-info'); +}); diff --git a/languages/sqlite-integration-ja.mo b/languages/sqlite-integration-ja.mo new file mode 100644 index 0000000000000000000000000000000000000000..a5db75e298886f9d8b242f19357071ea49ef7cc3 GIT binary patch literal 43052 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 literal 0 HcmV?d00001 diff --git a/languages/sqlite-integration-ja.po b/languages/sqlite-integration-ja.po new file mode 100644 index 0000000..2c6c093 --- /dev/null +++ b/languages/sqlite-integration-ja.po @@ -0,0 +1,1198 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2013 THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Kojima Toshiyasu , 2013. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-05-21 13:11+0900\n" +"PO-Revision-Date: 2013-05-21 13:11+0900\n" +"Last-Translator: Kojima Toshiyasu \n" +"Language-Team: LANGUAGE \n" +"Language: Japanese\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: db.php:46 +msgid "PHP version on this server is too old." +msgstr "お使いのPHPが古すぎます。" + +#: db.php:46 +#, php-format +msgid "" +"Your server is running PHP version %d but this version of WordPress requires " +"at least 5.2.4" +msgstr "" +"PHP%dをお使いになっていますが、WordPressには5.2.4以上が必要です。" + +#: db.php:50 +msgid "PHP PDO Extension is not loaded." +msgstr "PHPのPDOエクステンションがロードされていません。" + +#: db.php:50 +msgid "" +"Your PHP installation appears to be missing the PDO extension which is " +"required for this version of WordPress." +msgstr "" +"このWordPressで必要とされるPHPのPDOエクステンションが欠けているようです。" + +#: db.php:54 +msgid "PDO Driver for SQLite is missing." +msgstr "PDOのSQLite用ドライバがありません。" + +#: db.php:54 +msgid "" +"Your PHP installtion appears not to have the right PDO drivers loaded. These " +"are required for this version of WordPress and the type of database you have " +"specified." +msgstr "" +"お使いのPHPでは、必要なPDOドライバがロードされていないようです。これは、WordPressとデータベースを運用するのに" +"必要です。" + +#: install.php:42 +msgid "" +"Note that password carefully! It is a random password that was generated just for you." +msgstr "" +"注意してパスワードを控えてください! これはランダムに" +"作成されたものです。" + +#: install.php:47 +msgid "Your chosen password." +msgstr "あなたが決めたパスワード。" + +#: install.php:58 +msgid "The password you chose during the install." +msgstr "インストールのときにあなたが決めたパスワード。" + +#: pdodb.class.php:96 +#, php-format +msgid "WordPress database error %1$s for query %2$s made by %3$s" +msgstr "WordPressデータベースエラー%1$s。クエリは%2$s。%3$sが作成しました。" + +#: pdodb.class.php:98 +#, php-format +msgid "WordPress database error %1$s for query %2$s" +msgstr "WordPressデータベースエラー%1$s。クエリは%2$s。" + +#: pdodb.class.php:134 +#, php-format +msgid "" +"

Error establlishing a database connection

We have been unable to " +"connect to the specified database.
The error message received was %s" +msgstr "" +"

データベース接続エラー

データベースに接続できませんでした。
エラーメッセージは、%sです。" + +#: pdoengine.class.php:80 pdoengine.class.php:96 schema.php:26 +msgid "Database connection error!
" +msgstr "データベース接続エラー!
" + +#: pdoengine.class.php:81 pdoengine.class.php:97 schema.php:27 schema.php:81 +msgid "Error message is: %s" +msgstr "エラーメッセージは: " + +#: pdoengine.class.php:115 +msgid "" +"Unable to create the required directory! Please check your server settings." +msgstr "" +"必要なディレクトリが作成できませんでした。サーバ設定を確認してください。" + +#: pdoengine.class.php:120 pdoengine.class.php:126 +msgid "" +"Unable to create a file in the directory! Please check your server settings." +msgstr "" +"ディレクトリにファイルを作成できませんでした。サーバ設定を確認してください。" + +#: pdoengine.class.php:148 +#, php-format +msgid "" +"

Unknown query type

Sorry, we cannot determine the type of query " +"that is requested.

The query is %s

" +msgstr "" +"

未知のクエリ

申し訳ありません、要求されたクエリのタイプを決定できません。

クエリは%s" +"です。

" + +#: pdoengine.class.php:294 +#, php-format +msgid "Problem preparing the PDO SQL Statement. Error was: %s" +msgstr "SQLステートメントの準備中に問題。エラーは: %s" + +#: pdoengine.class.php:327 +#, php-format +msgid "Error while executing query! Error message was: %s" +msgstr "クエリの実行中にエラー! エラーメッセージは: %s" + +#: pdoengine.class.php:381 +msgid "The query is too big to parse properly" +msgstr "クエリが長すぎて解析できません" + +#: pdoengine.class.php:583 +#, php-format +msgid "Problem in creating table or index. Error was: %s" +msgstr "テーブルまたはインデックスを作成中に問題発生。エラーは: %s" + +#: pdoengine.class.php:626 +#, php-format +msgid "Problem in executing alter query. Error was: %s" +msgstr "ALTERクエリを実行中に問題発生。エラーは: %s" + +#: schema.php:80 +#, php-format +msgid "" +"Error occured while creating tables or indexes...
Query was: %s
" +msgstr "" +"テーブルまたはインデックスを作成中にエラー発生。
クエリは: %s
" + +#: sqlite-integration.php:158 sqlite-integration.php:181 +msgid "SQLite Integration" +msgstr "" + +#: utilities/documentation.php:17 utilities/documentation.php:19 +#: utilities/patch.php:157 utilities/patch.php:159 utilities/utility.php:382 +#: utilities/utility.php:384 utilities/utility.php:555 +#: utilities/utility.php:557 +msgid "You are not allowed to access this page!" +msgstr "このページにアクセスする権限がありません!" + +#: utilities/documentation.php:24 utilities/documentation.php:31 +#: utilities/patch.php:217 utilities/utility.php:354 utilities/utility.php:389 +#: utilities/utility.php:601 +msgid "Documentation" +msgstr "ドキュメント" + +#: utilities/documentation.php:25 utilities/patch.php:218 +#: utilities/utility.php:358 utilities/utility.php:390 +#: utilities/utility.php:602 +msgid "System Info" +msgstr "システム情報" + +#: utilities/documentation.php:26 utilities/patch.php:219 +#: utilities/utility.php:362 utilities/utility.php:391 +#: utilities/utility.php:603 +msgid "Miscellaneous" +msgstr "いろいろなもの" + +#: utilities/documentation.php:27 utilities/patch.php:220 +#: utilities/utility.php:366 utilities/utility.php:392 +#: utilities/utility.php:604 +msgid "Patch Utility" +msgstr "パッチをあてる" + +#: utilities/documentation.php:33 +msgid "" +"This is a brief documentation about this plugin. For more details, see also " +"the Plugin " +"Page." +msgstr "" +"このプラグインについての短いドキュメントです。詳しくは、プラグインのページをご覧ください。" + +#: utilities/documentation.php:36 +msgid "" +"Please don't forget: WordPress DOES NOT OFFICIALLY SUPPORT any database " +"other than MySQL. So if you ask about this plugin in the Forum, it's not " +"unlikely that you won't get no answers at all." +msgstr "" +"忘れないでください。WordPressが正式にサポートしているのはMySQLだけです。だから、フォーラムで質問しても、" +"回答が得られることは少ないでしょう。" + +#: utilities/documentation.php:39 +msgid "Features" +msgstr "機能" + +#: utilities/documentation.php:41 +msgid "" +"This plugin is a successor to PDO for WordPress, which enabled WordPress to use " +"SQLite for its database. But PDO for WordPress doesn't seem to be maintained " +"any more only to be outdated. SQLite Integration makes use of the basic ideas " +"and framework of PDO for WordPress, adds some new features and updates it to " +"be able to work with the newest version of WordPress(3.5.1 and 3.6 beta)." +msgstr "" +"このプラグインは" +"PDO for WordPressの後継です。PDO for WordPressはWordPressでSQLiteを使えるようにする" +"ものでしたが、もうメンテナンスされていないようで、古くなってしまいました。SQLite Integrationは、その基本的な" +"考えと枠組みを使って、新たな機能を追加し、最新のWordPress(3.5.1および3.6ベータ)で動作するように" +"したものです。" + +#: utilities/documentation.php:44 +msgid "" +"SQLite Web Page says — SQLite " +"is a "software library that implements selfcontained, serverless, zero-" +"configuration, transactional SQL database engine". It is "a good " +"choice for small to medium size websites". It's small and portable, and " +"you don't need any database server system." +msgstr "" +"SQLiteのサイトにはこうあります—SQLite" +"は、"他に何もいらず、サーバもサーバ設定も必要としない、トランザクションをサポートしたデータベースエンジン" +"のライブラリです"。"小規模・中規模のウェブサイトによく合います"。小さくてポータブル、" +"データベース・サーバなしでも使えるデータベースです。" + +#: utilities/documentation.php:47 +msgid "" +"Unfortunately enough, WordPress only supports MySQL. Consequently it doesn't " +"provide any APIs for SQLite. So if you want to create a website using " +"WordPress without a database server, you've got to write a kind of wrapper " +"program yourself to use SQLite. This is the way SQLite Integration goes." +msgstr "" +"残念なことに、WordPressはMySQLだけしかサポートしていません。そのため、SQLite用のAPIのようなものも" +"存在しません。だから、データベース・サーバなしでWordPressを使い、ウェブサイトを作ろうと思ったら、ある種の" +"ラッパ・プログラムを書かなければなりません。これが、SQLite Integrationです。" + +#: utilities/documentation.php:50 +msgid "SQLite Integration does the work as follows:" +msgstr "SQLite Integrationは次のように動作します:" + +#: utilities/documentation.php:53 +msgid "Intercepts SQL statement for MySQL from WordPress" +msgstr "WordPressからMySQLに発行されるSQLステートメントをインターセプトします" + +#: utilities/documentation.php:54 +msgid "Rewrites it as SQLite can execute" +msgstr "SQLiteが実行できる形に書き換えます" + +#: utilities/documentation.php:55 +msgid "Gives it to SQLite" +msgstr "SQLiteに実行させます" + +#: utilities/documentation.php:56 +msgid "Gets the results from SQLite" +msgstr "SQLiteから結果を受け取ります" + +#: utilities/documentation.php:57 +msgid "Format the results as MySQL returns, if necessary" +msgstr "必要があれば、その結果をMySQLが返す形に整形します" + +#: utilities/documentation.php:58 +msgid "Gives back the results to WordPress" +msgstr "WordPressに結果を返します" + +#: utilities/documentation.php:61 +msgid "" +"WordPress doesn't know what has happened in the background and will be happy " +"with it." +msgstr "" +"WordPressは背後で何が起こっているかを知らず、普通通り動作を続けます。" + +#: utilities/documentation.php:64 +msgid "Limitations" +msgstr "できないこと" + +#: utilities/documentation.php:66 +msgid "" +"SQLite Integration uses SQLite, so the limitations of SQLite is, as it is, " +"those of SQLite Integration. MySQL is far from a simple SQL engine and has " +"many extended features and functionalities. WordPress uses some of them. " +"Among those are some SQLite doesn't implement. For those features that " +"WordPress uses, I made them work with SQLite Integration. But for others that " +"some plugins are using, SQLite Integration can't manipulate. So..." +msgstr "" +"SQLite IntegrationはSQLiteを使います。だから、SQLiteの限界がそのまま、SQLite Integrationの" +"限界になります。MySQLは単純なSQLエンジンなどというものではなくて、たくさんの拡張機能があります。" +"WordPressもそれを使っています。その中には、SQLiteが実装していないものもあります。こうした機能については、" +"SQLite Integrationが動作するようにしました。でも、他のプラグインが使っているようなもので、SQLite Integration" +"が扱えないものもあります。だから..." + +#: utilities/documentation.php:69 +msgid "There are some plugins that you can't use in any way.
" +msgstr "どうしても使えないプラグインがあります。" + +#: utilities/documentation.php:70 +msgid "" +"Some plugins can't be activated or work properly. See the "Plugin " +"Compatibility/Incompatibility" section." +msgstr "" +"プラグインの中には、有効化できなかったり、うまく動作しなかったりするものがあります。「プラグインの互換性」" +"セクションをご覧ください。" + +#: utilities/documentation.php:71 +msgid "" +"There are some plugins that you can't use without rewriting some codes in " +"them.
" +msgstr "" +"中のコードを書き換えなければ動作しないプラグインがあります。
" + +#: utilities/documentation.php:72 +#, php-format +msgid "" +"Some plugins do work fine if you rewrite MySQL functions. I made some patch " +"files and Patch Utility. See also the Plugin Page for " +"more details." +msgstr "" +"MySQLの関数を書き換えると動作するプラグインがあります。いくつかはパッチファイルと、" +"パッチをあてるページを作りました。" +"プラグインのページもご覧ください。" + +#: utilities/documentation.php:75 +msgid "" +"And there may be other problems I overlooked. If you find malfunctionality, " +"please let me know at the Support Forum." +msgstr "" +"見逃している問題があるかもしれません。不具合を見つけたら、サポートフォーラムでお知らせください。" + +#: utilities/documentation.php:77 +msgid "User Defined Functions" +msgstr "ユーザ定義関数" + +#: utilities/documentation.php:79 +msgid "" +"SQLite Integration replaces some functions of MySQL with the user defined " +"functions built in PHP PDO library. But some of the functions are " +"meaningless in SQLite database: e.g. get_lock() or release_lock(). When " +"SQLite Integration meets those functions, it does nothing but prevent the " +"error." +msgstr "" +"SQLite IntegrationはMySQLの関数をPDOライブラリの提供するユーザ定義関数のしくみを使って" +"書き換えます。でも、SQLiteでは意味のない関数もあります。たとえば、get_lock()やrelease_lock()" +"などです。SQLite Integrationは、これらの関数がエラーを出さないようにする以外のことをしていません。" + +#: utilities/documentation.php:82 +msgid "" +"If you want SQLite Integration to execute more functions, you can add the " +"definition in the file sqlite-integration/functions.php (functions-5-2.php is " +"for PHP 5.2 or lesser)." +msgstr "" +"SQLite Integrationにもっとさくさんの関数を実行させたいときには、sqlite-integration/functions.php" +"(functions-5-2.phpはPHP5.2以前用です)に定義を追加することができます。" + +#: utilities/documentation.php:85 +msgid "Database Administration and Maintenance" +msgstr "データベース管理・メンテナンス" + +#: utilities/documentation.php:87 +msgid "" +"SQLite Integration doesn't contain database maintenace functionality, because " +"there are some other free or proprietary softwares that give you such " +"functionalities. For example, these are among free softwares:" +msgstr "" +"SQLite Integrationはメンテナンスの機能を持っていません。というのは、他に同じ機能を提供することができる、" +"フリーや独占ソフトウェアがあるからです。フリー・ソフトウェアには、次のようなものがあります。" + +#: utilities/documentation.php:90 +msgid "my recommendation" +msgstr "お勧めです" + +#: utilities/documentation.php:91 +msgid "unfortunately seems not to maintained..." +msgstr "残念なことにあまり活発に開発されていないようです..." + +#: utilities/documentation.php:94 +msgid "" +"I'm not sure if future release may have some of the database maintenance " +"functionality." +msgstr "" +"将来のリリースでデータベースのメンテナンス機構を組み込むかどうかはわかりません。" + +#: utilities/documentation.php:100 +msgid "Plugin Compatibility/Incompatibility" +msgstr "プラグインの互換性/非互換性" + +#: utilities/documentation.php:102 +msgid "" +"WordPress without its plugins is a king without people. Of course, you need " +"plugins, I know." +msgstr "" +"プラグインなしのWordPressは、国民のいない王様です。プラグインが使えなければなりません。" + +#: utilities/documentation.php:105 +#, php-format +msgid "" +"Most of the plugins will work fine with this plugin. But there are some that " +"you need to rewrite some codes in them, and there are others that you can't " +"use with this plugin. This is the list of the problematic plugins (far from " +"complete). You can see informations about your installed plugins in the System Info page. To see more details, please " +"visit the Plugin Page." +msgstr "" +"ほとんどのプラグインはうまく動作するでしょう。でも、コードを書き換えなければ使えないものや、何をしても使えないもの" +"もあります。下の表は、問題のあるプラグインです(完全なものではありません)。インストール済みのプラグインについては、" +"システム情報のページをご覧ください。より詳細な情報は、" +"プラグインのページ" +"をご覧ください。" + +#: utilities/documentation.php:111 +msgid "Plugins Name" +msgstr "プラグイン名" + +#: utilities/documentation.php:112 +msgid "Compatibility" +msgstr "互換性" + +#: utilities/documentation.php:113 +msgid "Reasons" +msgstr "理由" + +#: utilities/documentation.php:127 utilities/utility.php:239 +#: utilities/utility.php:241 +msgid "Needs Patch" +msgstr "パッチが必要" + +#: utilities/documentation.php:129 utilities/utility.php:245 +msgid "Probably No" +msgstr "たぶん不可" + +#: utilities/documentation.php:131 utilities/utility.php:251 +msgid "No" +msgstr "不可" + +#: utilities/documentation.php:141 +msgid "Caching Plugins" +msgstr "キャッシュ用プラグイン" + +#: utilities/documentation.php:143 +msgid "" +"Some plugins that give you cache functinality might cause problems. It is " +"because they try to create the db.php file in wp-content directory, which " +"file SQLite Integration is using." +msgstr "" +"キャッシュの機能を提供するプラグインの中には問題になるものがあります。wp-contentディレクトリにdb.php" +"ファイルを作ろうとするのですが、SQLite Integrationがすでにそれを使ってしまっているからです。" + +#: utilities/documentation.php:146 +msgid "" +"If those plugins overwrite the db.php file, SQLite Integration doesn't work. " +"My recommendation is not to use caching plugins. " +"Even so, if you want a caching plugin, you could try WP Super Cache, which " +"doesn't use db.php file. But no warranty, try at your own risk." +msgstr "" +"これらのプラグインがdb.phpファイルを上書きすると、SQLite Integrationは動作しなくなります。" +"私のお勧めは、キャッシュ・プラグインを使わないというものです。" +"それでも、どうしても使いたいということであれば、WP Super Cacheのようなものなら試せるかもしれません。db.phpを使わない" +"からです。でも、保証はありません。ご自分の責任でお試しください。" + +#: utilities/documentation.php:149 +msgid "I have not tested none of those caching plugins." +msgstr "私はこれらのキャッシュ・プラグインをテストしていません。" + +#: utilities/documentation.php:151 +msgid "MySQL specific functions" +msgstr "MySQL用の関数" + +#: utilities/documentation.php:153 +msgid "" +"Some plugins don't use WordPress database functions such as dbDelta(), and " +"use PHP native MySQL functions when they create and manage tables in the " +"database. But PHP doesn't permit redefining of the native functions (at " +"least, under ordinary server setting). So SQLite Integration can't intercept " +"and rewrite those functions." +msgstr "" +"プラグインの中にはデータベースにアクセスするのに、WordPressが提供するdbDelta()のような関数を使わず、" +"PHPのmysqlドライバの提供する関数を使って、テーブルを作ったり、操作したりするものがあります。PHPは組み込み" +"の関数を再定義することを許しません(少なくとも通常のサーバ設定では)。だから、SQLite Integrationは" +"それらをインターセプトして、書き換えることができません。" + +#: utilities/documentation.php:156 +msgid "For example, you can see these codes in Google XML Sitemaps." +msgstr "たとえば、Google XML Sitemapsにはこのようなコードがあります。" + +#: utilities/documentation.php:162 +msgid "or in Camera Slideshow" +msgstr "あるいは、Camera Slideshowには、こんな部分があります。" + +#: utilities/documentation.php:168 +msgid "" +"Such functions as mysql_get_server_info() or mysql_query() are from the " +"MySQL driver of PHP. Not only some plugins but WordPress uses them, but " +"SQLite Integration has no way to rewrite or redefine them. If the plugin you " +"want to use has those functions in it, it won't work or give the error " +"messages." +msgstr "" +"mysql_get_server_info()やmysql_query()といった関数は、PHPのドライバが提供するものです。" +"でも、SQLite Integrationはこれらを書き換えたり、再定義したりすることができません。もし、あなたが" +"使いたいプラグインがこれらの関数を使っていたら、うまく動かないか、エラー・メッセージが出るでしょう。" + +#: utilities/documentation.php:171 +msgid "" +"So, you have to rewrite them for SQLite Integration can execute. The two " +"example above can be rewritten like this:" +msgstr "" +"だから、これらの関数は手動で書き換えなければ、SQLite Integrationで実行できません。上の2つの" +"例は、次のように書き換えればうまくいきます。" + +#: utilities/documentation.php:180 +msgid "" +"As for those functions in WordPress, I overrode the WordPress functions " +"themselves that contains such MySQL functions as mysql_query() or " +"mysql_real_escape_string()." +msgstr "" +"WordPressで使われているこれらの関数については、mysql_query()やmysql_real_escape_string()" +"といった関数を含むWordPress関数をオーバーライドしています。" + +#: utilities/documentation.php:182 +msgid "FULLTEXT index" +msgstr "FULLTEXTインデックス" + +#: utilities/documentation.php:184 +msgid "" +"Some plugins use FULLTEXT index of MySQL. Of course SQLite does have the " +"functionality named "full-text search". But it is not correlated " +"with that of MySQL. In fact it is not an "index" and requires " +"another new table for that. And it has a different syntax. So you can't use " +"the plugins which uses FULLTEXT index" +msgstr "" +"プラグインの中には、MySQLのFULLTEXTインデックスを使うものがあります。もちろん、SQLiteにも、"" +"full-text search"という機能があります。でも、これはMySQLのものとは違います。、実際は" +"インデックスではなく、新たなテーブルを作らなければならないものです。構文も異なります。だから、FULLTEXT" +"インデックスを使うプラグインは使うことができません。" + +#: utilities/documentation.php:187 +msgid "" +"If your language is not written by separating words with spaces, e.g. " +"Japanese, Chinese or Thai, neither FULLTEXT index nor full-text search work " +"effectively. Even if your language is space-separating-words one, you don't " +"have to be disappointed. Whatever languages you use, you can use WordPress Related Posts or Related Posts or others. They are working fine " +"with SQLite Integration!" +msgstr "" +"あなたの言語が、日本語や中国語やタイ語のように、スペースで単語を区切らない言語の場合、FULLTEXT" +"インデックスもfull-text searchも有効に働きません。あなたの言語が分かち書きをするものだとしても、" +"がっかりする必要はありません。WordPress Related PostsRelated Postsのうようなプラグインを" +"使うことができます。これらは、SQLite Integrationでちゃんと動作します。" + +#: utilities/patch.php:53 +msgid "Patch command is not found" +msgstr "パッチコマンドがありません" + +#: utilities/patch.php:56 +msgid "Patch command is not executable" +msgstr "パッチコマンドが実行可能ではありません" + +#: utilities/patch.php:73 +msgid "Patch file name is invalid" +msgstr "パッチファイルが不正です" + +#: utilities/patch.php:77 +msgid "Patch file version does not match with that of your plugin." +msgstr "パッチファイルのバージョンがプラグインのものと一致しません。" + +#: utilities/patch.php:86 +msgid "Error! Plugin directory is not accessible." +msgstr "エラーです。プラグインのディレクトリにアクセスできません。" + +#: utilities/patch.php:89 +msgid "is patched successfully." +msgstr "パッチを適用しました。" + +#: utilities/patch.php:94 utilities/patch.php:121 +#, php-format +msgid "Error! Messages: %s" +msgstr "エラー。メッセージは: %s" + +#: utilities/patch.php:118 +msgid "Error!: patches directory is not accessible." +msgstr "エラー。パッチディレクトリにアクセスできません。" + +#: utilities/patch.php:123 +#, php-format +msgid "File %s is deleted." +msgstr "ファイル%sは削除されました。" + +#: utilities/patch.php:138 +msgid "File is uploaded" +msgstr "ファイルをアップロードしました" + +#: utilities/patch.php:142 +msgid "File is not uploaded" +msgstr "ファイルのアップロードができませんでした" + +#: utilities/patch.php:146 +msgid "File is not selected" +msgstr "ファイルが選択されていません" + +#: utilities/patch.php:164 utilities/patch.php:166 utilities/patch.php:186 +#: utilities/patch.php:188 utilities/patch.php:208 utilities/patch.php:210 +msgid "You are not allowed to do this operation!" +msgstr "この操作をする権限がありません" + +#: utilities/patch.php:170 utilities/patch.php:192 +msgid "Please select patch file(s)" +msgstr "パッチファイルを選択してください" + +#: utilities/patch.php:179 +msgid "None of the patches is applied!" +msgstr "パッチは適用されませんでした。" + +#: utilities/patch.php:201 +msgid "Error! Please remove files manually" +msgstr "エラー。ファイルを手動で削除してください。" + +#: utilities/patch.php:224 +msgid "Patch Files Upload and Apply" +msgstr "パッチファイルのアップロードと適用" + +#: utilities/patch.php:225 +msgid "What you can do in this page" +msgstr "このページでできること" + +#: utilities/patch.php:227 +msgid "" +"I made patch files for some plugins that are incompatible with SQLite " +"Integration and need rewriting. And I wrote in the Plugin Page about how to apply a " +"patch file to the plugin. But the command line interface sometimes " +"embarrasses some people, especially newbies." +msgstr "" +"SQLite Integrationで使えないプラグインのために、いくつかパッチファイルを作りました。プラグイン・ページで適用の仕方を書きましたが、コマンドライン" +"での操作が苦手な人もいます。初心者は特にそうでしょう。" + +#: utilities/patch.php:230 +msgid "" +"In this page, you can upload patch files and apply them automatically. But " +"there are some requirements." +msgstr "" +"このページでは、パッチファイルをアップロードして、自動的にそれを適用することができます。でも、いくつかの必要" +"要件があります。" + +#: utilities/patch.php:233 +msgid "" +"Think before you leap. Is the plugin to which you are going to apply patch " +"really necessary for your site? Did you search in the Plugin Directory for the substitutes?" +msgstr "" +"使う前によく考えましょう。パッチを適用しようとしているプラグインは本当にあなたのサイトに必要ですか?" +"Plugin Directory" +"で代わりになるプラグインを探してみましたか?" + +#: utilities/patch.php:234 +msgid "" +"Your PHP script has the permission to create a directory and write a file in " +"it." +msgstr "" +"PHPスクリプトがディレクトリやファイルを作成する権限を持っていなければなりません。" + +#: utilities/patch.php:235 +msgid "Your PHP scripts can execute exec() function on the server." +msgstr "PHPスクリプトがサーバ上で、exec()関数を実行できること。" + +#: utilities/patch.php:236 +msgid "" +"Your PHP script can execute "patch" shell command.(Script will " +"check if it is executable or not.)" +msgstr "" +"PHPスクリプトが"patch"シェルコマンドを実行できること(実行可能かどうかはスクリプトが" +"チェックします)。" + +#: utilities/patch.php:239 +msgid "" +"If uploading fails, it' very likely that application will fail. When you try " +"uploading with FTP client, the patch files must be put into the directory wp-" +"content/uploads/patches/. When constant UPLOADS is defined, script follows it." +msgstr "" +"ファイルのアップロードが失敗する場合は、パッチの適用も失敗する可能性があります。FTPクライアントでアップロード" +"するときは、wp-content/uploads/patchesディレクトリに入るようにしてください。UPLOADS定数が定義されている" +"場合はそれに従います。" + +#: utilities/patch.php:242 +msgid "" +"You can create your patch file yourself. When you create one, please test it " +"on your local server first and check if it works fine without PHP error or " +"notice ( set error_reporting(E_ALL) ). If you use this utility, name your " +"patch file as follows:" +msgstr "" +"自分でパッチファイルを作ることもできます。作ったら、ローカルのサーバでまずテストをして、PHPエラーや注意が" +"出ていないことを確認してください(error_reposting(E_ALL)をセットするとよい)。このページで使いたい" +"場合は、次のように名前をつけてください。" + +#: utilities/patch.php:245 +msgid "Use the file name beginning with the plugin directory name." +msgstr "プラグインのディレクトリ名で始まる名前にする。" + +#: utilities/patch.php:246 +msgid "Use the plugin version number after the directory name with underscore." +msgstr "ディレクトリ名の後にアンダースコアとバージョン番号を使う。" + +#: utilities/patch.php:247 +msgid "Use the suffix .patch." +msgstr ".patchを拡張子にする。" + +#: utilities/patch.php:248 +msgid "Use diff command options "-Naur"." +msgstr "diffコマンドには"-Naur"オプションを使う。" + +#: utilities/patch.php:251 +msgid "" +"For example, the patch file for the plugin "Debug Bar" is "" +"debug-bar_0.8.patch". Script interprets "debug-bar" as the " +"target directory and "0.8" as the target version. If the version " +"number doesn't match with the target, script shows the error message and " +"skip applying the patch file. And script will reject any other file name." +msgstr "" +"たとえば、"Debug Bar"のパッチファイルを作るとすると、"debug-bar_0.8.patch"" +"という名前になります。スクリプトは"debug-bar"を対象のディレクトリとして、"0.8"" +"を対象のバージョンとして解釈します。バージョン番号が対象のものと一致しない場合は、スクリプトはエラー・メッセージ" +"を出力して、実行を中断します。他のファイル名の場合は実行しません。" + +#: utilities/patch.php:254 +msgid "How to install, patch and activate plugins" +msgstr "プラグインのインストール、パッチ、有効化のしかた" + +#: utilities/patch.php:256 +msgid "Install the plugin (not yet activate it)" +msgstr "プラグインをインストールします(まだ有効化しないでください)" + +#: utilities/patch.php:257 +msgid "Upload the patch file (if any) to the server and ppply it in this page" +msgstr "パッチファイルがあれば、アップロードし、適用します" + +#: utilities/patch.php:258 +msgid "Back to the installed plugin page and activate it" +msgstr "インストール済みプラグインのページに戻り、有効化します" + +#: utilities/patch.php:260 +msgid "How to upgrade plugins" +msgstr "プラグインのアップグレードのしかた" + +#: utilities/patch.php:262 +msgid "When upgrading the plugin, it will be safer to follow next steps." +msgstr "プラグインをアップグレードするときは、安全のために次のステップに従ってください。" + +#: utilities/patch.php:265 +msgid "Deactivate the plugin" +msgstr "プラグインを無効化します" + +#: utilities/patch.php:266 +msgid "Upgrade the plugin" +msgstr "プラグインをアップグレードします" + +#: utilities/patch.php:267 +msgid "Upload the patch file (if any) and apply it" +msgstr "パッチファイルがあればそれをアップロードして適用します" + +#: utilities/patch.php:268 +msgid "Reactivate the plugin" +msgstr "再び有効化します" + +#: utilities/patch.php:270 +msgid "" +"If there isn't a patch file to match with the newest version of the plugin, " +"it won't work properly. Please wait for somebody to make one or rewrite the " +"codes checking the patch file for the previous version (it's not so " +"difficult a matter, I guess, for almost all the cases, you'll have only to " +"replace the MySQL functions with the WordPress built-in functions)." +msgstr "" +"もし、最新バージョンに対応するパッチファイルがない場合は、そのままアップグレードしてもうまく動作しないでしょう。" +"だれかがパッチを作るのを待つか、前バージョンのパッチを参考に自分で書き換えをしてください(それほど難しい" +"作業ではありません。多くの場合、MySQLの関数をWordPressの関数に置き換えるだけです)。" + +#: utilities/patch.php:271 +msgid "Upload and Apply" +msgstr "アップロードと適用" + +#: utilities/patch.php:275 +msgid "File Select" +msgstr "ファイルを選択" + +#: utilities/patch.php:282 +msgid "" +"Select file from your computer. If the file name is the same as existent " +"file, this operation will override it." +msgstr "" +"あなたのコンピュータにあるファイルを選択します。ファイル名がすでに存在する場合は、それを上書きします。" + +#: utilities/patch.php:284 +msgid "Upload" +msgstr "アップロード" + +#: utilities/patch.php:289 +msgid "Patch files uploaded" +msgstr "アップロードしたパッチファイル" + +#: utilities/patch.php:296 +msgid "" +"Select the file(s) you want to apply to the plugin(s) or you want to delete. " +"You can select multiple files." +msgstr "" +"プラグインに適用したいパッチファイル、または削除したいパッチファイルを選択してください。複数選択できます。" + +#: utilities/patch.php:300 +msgid "Apply/Hold" +msgstr "適用/保留" + +#: utilities/patch.php:301 +msgid "Patch files to apply" +msgstr "適用するパッチ" + +#: utilities/patch.php:317 +msgid "Apply patch" +msgstr "パッチを適用" + +#: utilities/patch.php:317 +msgid "" +"Are you sure to apply patch files?\\n\\nClick [Cancel] to stop,[OK] to " +"continue." +msgstr "" +"本当にパッチを適用してもよろしいですか?\\n\\nやめるなら[キャンセル]をクリック、続けるなら[OK]をクリック。" + +#: utilities/patch.php:318 +msgid "Delete file" +msgstr "ファイルを削除" + +#: utilities/patch.php:318 +msgid "" +"Are you sure to delete patch files?\\n\\nClick [Cancel] to stop,[OK] to " +"continue." +msgstr "" +"本当に削除してもよろしいですか?\\n\\nやめるなら[キャンセル]をクリック、続けるなら[OK]をクリック。" + +#: utilities/patch.php:329 +msgid "Caution about your patch file(s)" +msgstr "パッチファイルについての注意" + +#: utilities/patch.php:333 +msgid "" +"If you don't know where it comes from or who created it, I strongly " +"recommend that you should see and check the contents of the file. If a " +"person who created it secretly inserted a malicious codes, it will be " +"executed by the plugin and may damage your site or your server, for which " +"damage I don't incur any liability. If you don't understand well, you'd better use " +"the substitute plugins. Take your own risk, please." +msgstr "" +"素性のあやしいパッチファイルがあったら、ファイルの内容を確認することを強くお勧めします。作成者がひそかに" +"悪意のあるコードを仕込んでいると、プラグインがそれを実行してしまいます。あなたのサイトやサーバが被害を受ける" +"かもしれません。どんな被害が出ても、賠償には応じることはありません。よくわからない場合は、代替プラグイン" +"を使うことを考えてください。リスクを承知でお使いください。" + +#: utilities/utility.php:248 +msgid "Probably Yes" +msgstr "たぶん不可" + +#: utilities/utility.php:254 +msgid "Checked" +msgstr "チェック済" + +#: utilities/utility.php:257 utilities/utility.php:263 +msgid "Not Checked" +msgstr "未確認" + +#: utilities/utility.php:268 +msgid "Sitewide Active" +msgstr "ネットワークで有効" + +#: utilities/utility.php:271 +msgid "Active" +msgstr "有効" + +#: utilities/utility.php:274 +msgid "Inactive" +msgstr "無効" + +#: utilities/utility.php:336 +msgid "Welcome to SQLite Integration" +msgstr "SQLite Integrationにようこそ" + +#: utilities/utility.php:338 +msgid "Thank you for using SQLite Integration plugin!" +msgstr "SQLite Integrationをお使いいただき、ありがとうぐざいます。" + +#: utilities/utility.php:341 +msgid "" +"You read this message, which means you have succeeded in installing " +"WordPress with this plugin SQLite Integration. Congratulations and enjoy your " +"Blogging!" +msgstr "" +"このメッセージを読んでいるということは、インストールの成功したことを意味します。おめでとうございます。ブログをお楽しみ" +"ください。" + +#: utilities/utility.php:344 +msgid "" +"You don't have to set any special settings. In fact there are no other " +"settings. You can write articles or pages and customize you WordPress in an " +"ordinary way. You want to install your plugins? All right, go ahead. But " +"some of them may be incompatible with this. Please read more information " +"about this plugin and your SQLite database below." +msgstr "" +"特別な設定は必要ありません。実際、もう設定すべきことは残っていません。通常のとおり、投稿やページを書き、" +"WordPressをカスタマイズしたりできます。プラグインをインストールしたいですか? そうしましょう。でも、中には" +"使えないものもあります。プラグインやSQLiteデータベースについての情報をお読みください。" + +#: utilities/utility.php:346 +msgid "" +"Deactivation makes this documents and utilities disappear from the " +"dashboard, but it doesn't affect the functionality of the SQLite Integration. " +"when uninstalled, it will remove wp-content/uploads/patches directory (if " +"exists) and wp-content/db.php file altogether." +msgstr "" +"無効化すると、ダッシュボードからこのドキュメントとユーティリティを消すことができます。でも、SQLite Integration" +"の機能には影響ありません。削除のときは、もしあれば、wp-content/uploads/patchesディレクトリと、" +"wp-content/db.phpファイルを削除します。" + +#: utilities/utility.php:349 +msgid "Title" +msgstr "タイトル" + +#: utilities/utility.php:350 +msgid "Contents" +msgstr "コンテンツ" + +#: utilities/utility.php:355 +msgid "You can read documentation about this plugin and plugin compatibility." +msgstr "このプラグインについてのドキュメントとプラグインの互換性について読むことができます。" + +#: utilities/utility.php:359 +msgid "You can see database and system information." +msgstr "データベースとシステムの情報を見ることができます。" + +#: utilities/utility.php:363 +msgid "" +"You can see the error log and edit db.php file (if necessary) and optimize " +"your database." +msgstr "" +"エラー・ログを見たり、必要なら、db.phpを編集したり、データベースの最適化をしたりできます。" + +#: utilities/utility.php:367 +msgid "You can upload patch files and apply them to the incompatible plugins." +msgstr "パッチファイルをアップロードし、プラグインに適用できます。" + +#: utilities/utility.php:396 +msgid "System Information" +msgstr "システム情報" + +#: utilities/utility.php:397 +msgid "PHP Informations" +msgstr "PHP情報" + +#: utilities/utility.php:402 utilities/utility.php:438 +msgid "Items" +msgstr "項目" + +#: utilities/utility.php:403 +msgid "Description" +msgstr "説明" + +#: utilities/utility.php:408 +msgid "WordPress Version" +msgstr "WordPressのバージョン" + +#: utilities/utility.php:412 +msgid "PHP Version" +msgstr "PHPのバージョン" + +#: utilities/utility.php:416 +msgid "PDO Support" +msgstr "PDOサポート" + +#: utilities/utility.php:420 +msgid "PDO Drivers" +msgstr "PDOドライバ" + +#: utilities/utility.php:424 +msgid "PDO Driver for SQLite 3.x" +msgstr "SQLite 3.x用PDOドライバ" + +#: utilities/utility.php:428 +msgid "SQLite Library Version" +msgstr "SQLiteライブラリのバージョン" + +#: utilities/utility.php:434 +msgid "Your Database Status" +msgstr "データベースの状態" + +#: utilities/utility.php:439 +msgid "Status" +msgstr "状態" + +#: utilities/utility.php:445 +msgid "Database Size" +msgstr "データベースのサイズ" + +#: utilities/utility.php:449 +msgid "Page Size" +msgstr "ページサイズ" + +#: utilities/utility.php:453 +msgid "Total Number of Pages" +msgstr "合計のページ数" + +#: utilities/utility.php:457 +msgid "Unused Page" +msgstr "未使用ページ" + +#: utilities/utility.php:461 +msgid "Integrity Check" +msgstr "整合性チェック" + +#: utilities/utility.php:465 +msgid "Encoding" +msgstr "エンコーディング" + +#: utilities/utility.php:469 +msgid "Collations" +msgstr "照合順序" + +#: utilities/utility.php:481 +msgid "Compile Options" +msgstr "コンパイルオプション" + +#: utilities/utility.php:495 +msgid "Database Tables and Indexes" +msgstr "データベースのテーブルとインデックス" + +#: utilities/utility.php:497 +msgid "" +"Table names in brown are required by WordPress, and those in blue are " +"created by some plugins. The table sqlite_sequence is not a WordPress table " +"but a table required by SQLite to store the current autoincremented value of " +"each table, which is displayed in the parenthesis after the table names. You " +"can't manipulate the tables or indexes here. Please use SQLite utilities (e." +"g. SQLiteManager)." +msgstr "" +"茶色のテーブル名はWordPressが必要とするものです。青のテーブル名はプラグインが作ったものです。sqlite_sequence" +"テーブルはWordPressではなくて、SQLiteが必要とします。それぞれのテーブルの、オートインクリメントの現在値が" +"格納されています。この値は、テーブル名の隣に括弧つきで表示されます。テーブルやインデックスをここで操作" +"することはできません。SQLiteManagerのようなユーティリティをお使いください。" + +#: utilities/utility.php:502 +msgid "Table Name" +msgstr "テーブル名" + +#: utilities/utility.php:503 +msgid "System/User" +msgstr "システム/ユーザ" + +#: utilities/utility.php:504 +msgid "Index ( Column )" +msgstr "インデックス ( カラム名 )" + +#: utilities/utility.php:529 +msgid "Plugin Info" +msgstr "プラグイン情報" + +#: utilities/utility.php:531 +msgid "This table shows plugins you have installed and their compatibility." +msgstr "この表は、インストール済みのプラグインについて、互換性を表示します。" + +#: utilities/utility.php:536 +msgid "Installed Plugins" +msgstr "インストール済み" + +#: utilities/utility.php:537 +msgid "Active/Inactive" +msgstr "有効/無効" + +#: utilities/utility.php:538 +msgid "Compatible" +msgstr "互換性" + +#: utilities/utility.php:562 +msgid "Log cleared" +msgstr "ログをクリアしました" + +#: utilities/utility.php:565 +msgid "Log not cleared" +msgstr "ログがクリアされませんでした" + +#: utilities/utility.php:577 +msgid "db.php was saved" +msgstr "db.phpを保存しました" + +#: utilities/utility.php:580 +msgid "Error! db.php couldn't be saved" +msgstr "エラー。db.phpを保存できませんでした" + +#: utilities/utility.php:591 +#, php-format +msgid "" +"Optimization finished. Before optimization: %1$s, After optimization: %2$s." +msgstr "" +"最適化が終了しました。最適化前のサイズ: %1$s、最適化後のサイズ: %2$s。" + +#: utilities/utility.php:594 +msgid "Optimization failed" +msgstr "最適化に失敗しました" + +#: utilities/utility.php:608 +msgid "Database Optimization, Error Log, Init File" +msgstr "データベースの最適化、エラーログ、初期化ファイル" + +#: utilities/utility.php:609 +msgid "Optimize You Database" +msgstr "データベースを最適化する" + +#: utilities/utility.php:611 +msgid "" +"This button sends "vacuum" command to your SQLite database. That " +"command reclaims space after data has been deleted." +msgstr "" +"このボタンは"vaccum"コマンドをSQLiteデータベースに発行します。このコマンドは、" +"データの削除後に空いたスペースを回収します。" + +#: utilities/utility.php:619 +msgid "Optimize" +msgstr "最適化" + +#: utilities/utility.php:619 +msgid "" +"Are you sure to optimize your database?\\n\\nClick [Cancel] to stop, [OK] to " +"continue." +msgstr "" +"本当にデータベースを最適化しますか?\\n\\nやめるときは[キャンセル]を、続けるなら[OK]をクリック。" + +#: utilities/utility.php:622 +msgid "SQLite Integration Error Log" +msgstr "SQLite Integrationのエラーログ" + +#: utilities/utility.php:624 +msgid "" +"This is the contents of SQLite Integration error log file(default: wp-content/" +"database/debug.txt). If you want to clear this file, click the Clear Log " +"button." +msgstr "" +"SQLite Integrationが使うエラーログ・ファイルの内容です(デフォルトでは、wp-content/database/debug.txt)。" +"このファイルの内容をクリアするには、ログをクリアのボタンをクリックしてください。" + +#: utilities/utility.php:634 +msgid "No error messages are found" +msgstr "エラーメッセージはありません" + +#: utilities/utility.php:642 +msgid "Clear Log" +msgstr "ログをクリア" + +#: utilities/utility.php:642 +msgid "" +"Are you sure to clear Log?\\n\\nClick [Cancel] to stop, [OK] to continue." +msgstr "" +"本当にログをクリアしてもいいですか?\\n\\nやめるなら[キャンセル]を。続けるなら[OK]をクリック。" + +#: utilities/utility.php:646 +msgid "Edit Initial File (wp-content/db.php)" +msgstr "初期化ファイル(wp-content/db.php)を編集" + +#: utilities/utility.php:648 +msgid "" +"When you go "Plugins » Edit Plugin" page, you can edit " +"plugin source file. But you can't see this file there because it is not in " +"the plugin directory. If you need to edit this file, you can edit here. This " +"settings may cause problems. If you don't understand " +"well, please don't edit this file." +msgstr "" +""プラグイン » プラグインを編集"のページでは、プラグインのソースファイルを見ることができます。" +"でも、このファイルは別の場所にあるので、見ることができません。このファイルを編集する必要があるなら、ここで、編集" +"することができます。この設定は問題を起こすことがあります。よくわからない場合は" +"このファイルを変更しないでください。" + +#: utilities/utility.php:658 +msgid "Save" +msgstr "保存" + +#: utilities/utility.php:658 +msgid "" +"Are you sure to save this file?\\n\\nClick [Cancel] to stop, [OK] to " +"continue." +msgstr "" +"この内容を保存してもよろしいですか?\\n\\nやめるなら[キャンセル]を、続けるなら[OK]をクリック。" diff --git a/languages/sqlite-integration.pot b/languages/sqlite-integration.pot new file mode 100644 index 0000000..c736014 --- /dev/null +++ b/languages/sqlite-integration.pot @@ -0,0 +1,1057 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-05-21 13:11+0900\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: db.php:46 +msgid "PHP version on this server is too old." +msgstr "" + +#: db.php:46 +#, php-format +msgid "" +"Your server is running PHP version %d but this version of WordPress requires " +"at least 5.2.4" +msgstr "" + +#: db.php:50 +msgid "PHP PDO Extension is not loaded." +msgstr "" + +#: db.php:50 +msgid "" +"Your PHP installation appears to be missing the PDO extension which is " +"required for this version of WordPress." +msgstr "" + +#: db.php:54 +msgid "PDO Driver for SQLite is missing." +msgstr "" + +#: db.php:54 +msgid "" +"Your PHP installtion appears not to have the right PDO drivers loaded. These " +"are required for this version of WordPress and the type of database you have " +"specified." +msgstr "" + +#: install.php:42 +msgid "" +"Note that password carefully! It is a random password that was generated just for you." +msgstr "" + +#: install.php:47 +msgid "Your chosen password." +msgstr "" + +#: install.php:58 +msgid "The password you chose during the install." +msgstr "" + +#: pdodb.class.php:96 +#, php-format +msgid "WordPress database error %1$s for query %2$s made by %3$s" +msgstr "" + +#: pdodb.class.php:98 +#, php-format +msgid "WordPress database error %1$s for query %2$s" +msgstr "" + +#: pdodb.class.php:134 +#, php-format +msgid "" +"

Error establlishing a database connection

We have been unable to " +"connect to the specified database.
The error message received was %s" +msgstr "" + +#: pdoengine.class.php:80 pdoengine.class.php:96 schema.php:26 +msgid "Database connection error!
" +msgstr "" + +#: pdoengine.class.php:81 pdoengine.class.php:97 schema.php:27 schema.php:81 +msgid "Error message is: %s" +msgstr "" + +#: pdoengine.class.php:115 +msgid "" +"Unable to create the required directory! Please check your server settings." +msgstr "" + +#: pdoengine.class.php:120 pdoengine.class.php:126 +msgid "" +"Unable to create a file in the directory! Please check your server settings." +msgstr "" + +#: pdoengine.class.php:148 +#, php-format +msgid "" +"

Unknown query type

Sorry, we cannot determine the type of query " +"that is requested.

The query is %s

" +msgstr "" + +#: pdoengine.class.php:294 +#, php-format +msgid "Problem preparing the PDO SQL Statement. Error was: %s" +msgstr "" + +#: pdoengine.class.php:327 +#, php-format +msgid "Error while executing query! Error message was: %s" +msgstr "" + +#: pdoengine.class.php:381 +msgid "The query is too big to parse properly" +msgstr "" + +#: pdoengine.class.php:583 +#, php-format +msgid "Problem in creating table or index. Error was: %s" +msgstr "" + +#: pdoengine.class.php:626 +#, php-format +msgid "Problem in executing alter query. Error was: %s" +msgstr "" + +#: schema.php:80 +#, php-format +msgid "" +"Error occured while creating tables or indexes...
Query was: %s
" +msgstr "" + +#: sqlite-integration.php:158 sqlite-integration.php:181 +msgid "SQLite DB" +msgstr "" + +#: utilities/documentation.php:17 utilities/documentation.php:19 +#: utilities/patch.php:157 utilities/patch.php:159 utilities/utility.php:382 +#: utilities/utility.php:384 utilities/utility.php:555 +#: utilities/utility.php:557 +msgid "You are not allowed to access this page!" +msgstr "" + +#: utilities/documentation.php:24 utilities/documentation.php:31 +#: utilities/patch.php:217 utilities/utility.php:354 utilities/utility.php:389 +#: utilities/utility.php:601 +msgid "Documentation" +msgstr "" + +#: utilities/documentation.php:25 utilities/patch.php:218 +#: utilities/utility.php:358 utilities/utility.php:390 +#: utilities/utility.php:602 +msgid "System Info" +msgstr "" + +#: utilities/documentation.php:26 utilities/patch.php:219 +#: utilities/utility.php:362 utilities/utility.php:391 +#: utilities/utility.php:603 +msgid "Miscellaneous" +msgstr "" + +#: utilities/documentation.php:27 utilities/patch.php:220 +#: utilities/utility.php:366 utilities/utility.php:392 +#: utilities/utility.php:604 +msgid "Patch Utility" +msgstr "" + +#: utilities/documentation.php:33 +msgid "" +"This is a brief documentation about this plugin. For more details, see also " +"the Plugin " +"Page." +msgstr "" + +#: utilities/documentation.php:36 +msgid "" +"Please don't forget: WordPress DOES NOT OFFICIALLY SUPPORT any database " +"other than MySQL. So if you ask about this plugin in the Codex, it's not " +"unlikely that you won't get no answers at all." +msgstr "" + +#: utilities/documentation.php:39 +msgid "Features" +msgstr "" + +#: utilities/documentation.php:41 +msgid "" +"This plugin is a successor to PDO for WordPress, which enabled WordPress to use " +"SQLite for its database. But PDO for WordPress doesn't seem to be maintained " +"any more only to be outdated. SQLite Integration makes use of the basic ideas " +"and framework of PDO for WordPress, adds some new features and updates it to " +"be able to work with the newest version of WordPress(3.5.1 and 3.6 beta)." +msgstr "" + +#: utilities/documentation.php:44 +msgid "" +"SQLite Web Page says — SQLite " +"is a "software library that implements selfcontained, serverless, zero-" +"configuration, transactional SQL database engine". It is "a good " +"choice for small to medium size websites". It's small and portable, and " +"you don't need any database server system." +msgstr "" + +#: utilities/documentation.php:47 +msgid "" +"Unfortunately enough, WordPress only supports MySQL. Consequently it doesn't " +"provide any APIs for SQLite. So if you want to create a website using " +"WordPress without a database server, you've got to write a kind of wrapper " +"program yourself to use SQLite. This is the way SQLite Integration goes." +msgstr "" + +#: utilities/documentation.php:50 +msgid "SQLite Integration does the work as follows:" +msgstr "" + +#: utilities/documentation.php:53 +msgid "Intercepts SQL statement for MySQL from WordPress" +msgstr "" + +#: utilities/documentation.php:54 +msgid "Rewrites it as SQLite can execute" +msgstr "" + +#: utilities/documentation.php:55 +msgid "Gives it to SQLite" +msgstr "" + +#: utilities/documentation.php:56 +msgid "Gets the results from SQLite" +msgstr "" + +#: utilities/documentation.php:57 +msgid "Format the results as MySQL returns, if necessary" +msgstr "" + +#: utilities/documentation.php:58 +msgid "Gives back the results to WordPress" +msgstr "" + +#: utilities/documentation.php:61 +msgid "" +"WordPress doesn't know what has happened in the background and will be happy " +"with it." +msgstr "" + +#: utilities/documentation.php:64 +msgid "Limitations" +msgstr "" + +#: utilities/documentation.php:66 +msgid "" +"SQLite Integration uses SQLite, so the limitations of SQLite is, as it is, " +"those of SQLite Integration. MySQL is far from a simple SQL engine and has " +"many extended features and functionalities. WordPress uses some of them. " +"Among those are some SQLite doesn't implement. For those features that " +"WordPress uses, I made them work with SQLite Integration. But for others that " +"some plugins are using, SQLite Integration can't manipulate. So..." +msgstr "" + +#: utilities/documentation.php:69 +msgid "There are some plugins that you can't use in any way.
" +msgstr "" + +#: utilities/documentation.php:70 +msgid "" +"Some plugins can't be activated or work properly. See the "Plugin " +"Compatibility/Incompatibility" section." +msgstr "" + +#: utilities/documentation.php:71 +msgid "" +"There are some plugins that you can't use without rewriting some codes in " +"them.
" +msgstr "" + +#: utilities/documentation.php:72 +#, php-format +msgid "" +"Some plugins do work fine if you rewrite MySQL functions. I made some patch " +"files and Patch Utility. See also the Plugin Page for " +"more details." +msgstr "" + +#: utilities/documentation.php:75 +msgid "" +"And there may be other problems I overlooked. If you find malfunctionality, " +"please let me know at the Support Forum." +msgstr "" + +#: utilities/documentation.php:77 +msgid "User Defined Functions" +msgstr "" + +#: utilities/documentation.php:79 +msgid "" +"SQLite Integration replaces some functions of MySQL with the user defined " +"functions built in PHP PDO library. But some of the functions are " +"meaningless in SQLite database: e.g. get_lock() or release_lock(). When " +"SQLite Integration meets those functions, it does nothing but prevent the " +"error." +msgstr "" + +#: utilities/documentation.php:82 +msgid "" +"If you want SQLite Integration to execute more functions, you can add the " +"definition in the file sqlite-integration/functions.php (functions-5-2.php is " +"for PHP 5.2 or lesser)." +msgstr "" + +#: utilities/documentation.php:85 +msgid "Database Administration and Maintenance" +msgstr "" + +#: utilities/documentation.php:87 +msgid "" +"SQLite Integration doesn't contain database maintenace functionality, because " +"there are some other free or proprietary softwares that give you such " +"functionalities. For example, these are among free softwares:" +msgstr "" + +#: utilities/documentation.php:90 +msgid "my recommendation" +msgstr "" + +#: utilities/documentation.php:91 +msgid "unfortunately seems not to maintained..." +msgstr "" + +#: utilities/documentation.php:94 +msgid "" +"I'm not sure if future release may have some of the database maintenance " +"functionality." +msgstr "" + +#: utilities/documentation.php:100 +msgid "Plugin Compatibility/Incompatibility" +msgstr "" + +#: utilities/documentation.php:102 +msgid "" +"WordPress without its plugins is a king without people. Of course, you need " +"plugins, I know." +msgstr "" + +#: utilities/documentation.php:105 +#, php-format +msgid "" +"Most of the plugins will work fine with this plugin. But there are some that " +"you need to rewrite some codes in them, and there are others that you can't " +"use with this plugin. This is the list of the problematic plugins (far from " +"complete). You can see informations about your installed plugins in the System Info page. To see more details, please " +"visit the Plugin Page." +msgstr "" + +#: utilities/documentation.php:111 +msgid "Plugins Name" +msgstr "" + +#: utilities/documentation.php:112 +msgid "Compatibility" +msgstr "" + +#: utilities/documentation.php:113 +msgid "Reasons" +msgstr "" + +#: utilities/documentation.php:127 utilities/utility.php:239 +#: utilities/utility.php:241 +msgid "Needs Patch" +msgstr "" + +#: utilities/documentation.php:129 utilities/utility.php:245 +msgid "Probably No" +msgstr "" + +#: utilities/documentation.php:131 utilities/utility.php:251 +msgid "No" +msgstr "" + +#: utilities/documentation.php:141 +msgid "Caching Plugins" +msgstr "" + +#: utilities/documentation.php:143 +msgid "" +"Some plugins that give you cache functinality might cause problems. It is " +"because they try to create the db.php file in wp-content directory, which " +"file SQLite Integration is using." +msgstr "" + +#: utilities/documentation.php:146 +msgid "" +"If those plugins overwrite the db.php file, SQLite Integration doesn't work. " +"My recommendation is not to use caching plugins. " +"Even so, if you want a caching plugin, you could try WP Super Cache, which " +"doesn't use db.php file. But no warranty, try at your own risk." +msgstr "" + +#: utilities/documentation.php:149 +msgid "I have not tested none of those caching plugins." +msgstr "" + +#: utilities/documentation.php:151 +msgid "MySQL specific functions" +msgstr "" + +#: utilities/documentation.php:153 +msgid "" +"Some plugins don't use WordPress database functions such as dbDelta(), and " +"use PHP native MySQL functions when they create and manage tables in the " +"database. But PHP doesn't permit redefining of the native functions (at " +"least, under ordinary server setting). So SQLite Integration can't intercept " +"and rewrite those functions." +msgstr "" + +#: utilities/documentation.php:156 +msgid "For example, you can see these codes in Google XML Sitemaps." +msgstr "" + +#: utilities/documentation.php:162 +msgid "or in Camera Slideshow" +msgstr "" + +#: utilities/documentation.php:168 +msgid "" +"Such functions as mysql_get_server_info() or mysql_query() are from the " +"MySQL driver of PHP. Not only some plugins but WordPress uses them, but " +"SQLite Integration has no way to rewrite or redefine them. If the plugin you " +"want to use has those functions in it, it won't work or give the error " +"messages." +msgstr "" + +#: utilities/documentation.php:171 +msgid "" +"So, you have to rewrite them for SQLite Integration can execute. The two " +"example above can be rewritten like this:" +msgstr "" + +#: utilities/documentation.php:180 +msgid "" +"As for those functions in WordPress, I overrode the WordPress functions " +"themselves that contains such MySQL functions as mysql_query() or " +"mysql_real_escape_string()." +msgstr "" + +#: utilities/documentation.php:182 +msgid "FULLTEXT index" +msgstr "" + +#: utilities/documentation.php:184 +msgid "" +"Some plugins use FULLTEXT index of MySQL. Of course SQLite does have the " +"functionality named "full-text search". But it is not correlated " +"with that of MySQL. In fact it is not an "index" and requires " +"another new table for that. And it has a different syntax. So you can't use " +"the plugins which uses FULLTEXT index" +msgstr "" + +#: utilities/documentation.php:187 +msgid "" +"If your language is not written by separating words with spaces, e.g. " +"Japanese, Chinese or Thai, neither FULLTEXT index nor full-text search work " +"effectively. Even if your language is space-separating-words one, you don't " +"have to be disappointed. Whatever languages you use, you can use WordPress Related Posts or Related Posts or others. They are working fine " +"with SQLite Integration!" +msgstr "" + +#: utilities/patch.php:53 +msgid "Patch command is not found" +msgstr "" + +#: utilities/patch.php:56 +msgid "Patch command is not executable" +msgstr "" + +#: utilities/patch.php:73 +msgid "Patch file name is invalid" +msgstr "" + +#: utilities/patch.php:77 +msgid "Patch file version does not match with that of your plugin." +msgstr "" + +#: utilities/patch.php:86 +msgid "Error! Plugin directory is not accessible." +msgstr "" + +#: utilities/patch.php:89 +msgid "is patched successfully." +msgstr "" + +#: utilities/patch.php:94 utilities/patch.php:121 +#, php-format +msgid "Error! Messages: %s" +msgstr "" + +#: utilities/patch.php:118 +msgid "Error!: patches directory is not accessible." +msgstr "" + +#: utilities/patch.php:123 +#, php-format +msgid "File %s is deleted." +msgstr "" + +#: utilities/patch.php:138 +msgid "File is uploaded" +msgstr "" + +#: utilities/patch.php:142 +msgid "File is not uploaded" +msgstr "" + +#: utilities/patch.php:146 +msgid "File is not selected" +msgstr "" + +#: utilities/patch.php:164 utilities/patch.php:166 utilities/patch.php:186 +#: utilities/patch.php:188 utilities/patch.php:208 utilities/patch.php:210 +msgid "You are not allowed to do this operation!" +msgstr "" + +#: utilities/patch.php:170 utilities/patch.php:192 +msgid "Please select patch file(s)" +msgstr "" + +#: utilities/patch.php:179 +msgid "None of the patches is applied!" +msgstr "" + +#: utilities/patch.php:201 +msgid "Error! Please remove files manually" +msgstr "" + +#: utilities/patch.php:224 +msgid "Patch Files Upload and Apply" +msgstr "" + +#: utilities/patch.php:225 +msgid "What you can do in this page" +msgstr "" + +#: utilities/patch.php:227 +msgid "" +"I made patch files for some plugins that are incompatible with SQLite " +"Integration and need rewriting. And I wrote in the Plugin Page about how to apply a " +"patch file to the plugin. But the command line interface sometimes " +"embarrasses some people, especially newbies." +msgstr "" + +#: utilities/patch.php:230 +msgid "" +"In this page, you can upload patch files and apply them automatically. But " +"there are some requirements." +msgstr "" + +#: utilities/patch.php:233 +msgid "" +"Think before you leap. Is the plugin to which you are going to apply patch " +"really necessary for your site? Did you search in the Plugin Directory for the substitutes?" +msgstr "" + +#: utilities/patch.php:234 +msgid "" +"Your PHP script has the permission to create a directory and write a file in " +"it." +msgstr "" + +#: utilities/patch.php:235 +msgid "Your PHP scripts can execute exec() function on the server." +msgstr "" + +#: utilities/patch.php:236 +msgid "" +"Your PHP script can execute "patch" shell command.(Script will " +"check if it is executable or not.)" +msgstr "" + +#: utilities/patch.php:239 +msgid "" +"If uploading fails, it' very likely that application will fail. When you try " +"uploading with FTP client, the patch files must be put into the directory wp-" +"content/uploads/patches/." +msgstr "" + +#: utilities/patch.php:242 +msgid "" +"You can create your patch file yourself. When you create one, please test it " +"on your local server first and check if it works fine without PHP error or " +"notice ( set error_reporting(E_ALL) ). If you use this utility, name your " +"patch file as follows:" +msgstr "" + +#: utilities/patch.php:245 +msgid "Use the file name beginning with the plugin directory name." +msgstr "" + +#: utilities/patch.php:246 +msgid "Use the plugin version number after the directory name with underscore." +msgstr "" + +#: utilities/patch.php:247 +msgid "Use the suffix .patch." +msgstr "" + +#: utilities/patch.php:248 +msgid "Use diff command options "-Naur"." +msgstr "" + +#: utilities/patch.php:251 +msgid "" +"For example, the patch file for the plugin "Debug Bar" is "" +"debug-bar_0.8.patch". Script interprets "debug-bar" as the " +"target directory and "0.8" as the target version. If the version " +"number doesn't match with the target, script shows the error message and " +"skip applying the patch file. And script will reject any other file name." +msgstr "" + +#: utilities/patch.php:254 +msgid "How to install, patch and activate plugins" +msgstr "" + +#: utilities/patch.php:256 +msgid "Install the plugin (not yet activate it)" +msgstr "" + +#: utilities/patch.php:257 +msgid "Upload the patch file (if any) to the server and ppply it in this page" +msgstr "" + +#: utilities/patch.php:258 +msgid "Back to the installed plugin page and activate it" +msgstr "" + +#: utilities/patch.php:260 +msgid "How to upgrade plugins" +msgstr "" + +#: utilities/patch.php:262 +msgid "When upgrading the plugin, it will be safer to follow next steps." +msgstr "" + +#: utilities/patch.php:265 +msgid "Deactivate the plugin" +msgstr "" + +#: utilities/patch.php:266 +msgid "Upgrade the plugin" +msgstr "" + +#: utilities/patch.php:267 +msgid "Upload the patch file (if any) and apply it" +msgstr "" + +#: utilities/patch.php:268 +msgid "Reactivate the plugin" +msgstr "" + +#: utilities/patch.php:270 +msgid "" +"If there isn't a patch file to match with the newest version of the plugin, " +"it won't work properly. Please wait for somebody to make one or rewrite the " +"codes checking the patch file for the previous version (it's not so " +"difficult a matter, I guess, for almost all the cases, you'll have only to " +"replace the MySQL functions with the WordPress built-in functions)." +msgstr "" + +#: utilities/patch.php:271 +msgid "Upload and Apply" +msgstr "" + +#: utilities/patch.php:275 +msgid "File Select" +msgstr "" + +#: utilities/patch.php:282 +msgid "" +"Select file from your computer. If the file name is the same as existent " +"file, this operation will override it." +msgstr "" + +#: utilities/patch.php:284 +msgid "Upload" +msgstr "" + +#: utilities/patch.php:289 +msgid "Patch files uploaded" +msgstr "" + +#: utilities/patch.php:296 +msgid "" +"Select the file(s) you want to apply to the plugin(s) or you want to delete. " +"You can select multiple files." +msgstr "" + +#: utilities/patch.php:300 +msgid "Apply/Hold" +msgstr "" + +#: utilities/patch.php:301 +msgid "Patch files to apply" +msgstr "" + +#: utilities/patch.php:317 +msgid "Apply patch" +msgstr "" + +#: utilities/patch.php:317 +msgid "" +"Are you sure to apply patch files?\\n\\nClick [Cancel] to stop,[OK] to " +"continue." +msgstr "" + +#: utilities/patch.php:318 +msgid "Delete file" +msgstr "" + +#: utilities/patch.php:318 +msgid "" +"Are you sure to delete patch files?\\n\\nClick [Cancel] to stop,[OK] to " +"continue." +msgstr "" + +#: utilities/patch.php:329 +msgid "Caution about your patch file(s)" +msgstr "" + +#: utilities/patch.php:333 +msgid "" +"If you don't know where it comes from or who created it, I strongly " +"recommend that you should see and check the contents of the file. If a " +"person who created it secretly inserted a malicious codes, it will be " +"executed by the plugin and may damage your site or your server, for which " +"damage I incur any liability. If you don't understand well, you'd better use " +"the substitute plugins. Take your own risk, please." +msgstr "" + +#: utilities/utility.php:248 +msgid "Probably Yes" +msgstr "" + +#: utilities/utility.php:254 +msgid "Checked" +msgstr "" + +#: utilities/utility.php:257 utilities/utility.php:263 +msgid "Not Checked" +msgstr "" + +#: utilities/utility.php:268 +msgid "Sitewide Active" +msgstr "" + +#: utilities/utility.php:271 +msgid "Active" +msgstr "" + +#: utilities/utility.php:274 +msgid "Inactive" +msgstr "" + +#: utilities/utility.php:336 +msgid "Welcome to SQLite Integration" +msgstr "" + +#: utilities/utility.php:338 +msgid "Thank you for using SQLite Integration plugin!" +msgstr "" + +#: utilities/utility.php:341 +msgid "" +"You read this message, which means you have succeeded in installing " +"WordPress with this plugin SQLite Integration. Congratulations and enjoy your " +"Blogging!" +msgstr "" + +#: utilities/utility.php:344 +msgid "" +"You don't have to set any special settings. In fact there are no other " +"settings. You can write articles or pages and customize you WordPress in an " +"ordinary way. You want to install your plugins? All right, go ahead. But " +"some of them may be incompatible with this. Please read more information " +"about this plugin and your SQLite database below." +msgstr "" + +#: utilities/utility.php:346 +msgid "" +"Deactivation makes this documents and utilities disappear from the " +"dashboard, but it doesn't affect the functionality of the SQLite Integration. " +"when uninstalled, it will remove wp-content/uploads/patches directory (if " +"exists) and wp-content/db.php file altogether." +msgstr "" + +#: utilities/utility.php:349 +msgid "Title" +msgstr "" + +#: utilities/utility.php:350 +msgid "Contents" +msgstr "" + +#: utilities/utility.php:355 +msgid "You can read documentation about this plugin and plugin compatibility." +msgstr "" + +#: utilities/utility.php:359 +msgid "You can see database and system information." +msgstr "" + +#: utilities/utility.php:363 +msgid "" +"You can see the error log and edit db.php file (if necessary) and optimize " +"your database." +msgstr "" + +#: utilities/utility.php:367 +msgid "You can upload patch files and apply them to the incompatible plugins." +msgstr "" + +#: utilities/utility.php:396 +msgid "System Information" +msgstr "" + +#: utilities/utility.php:397 +msgid "PHP Informations" +msgstr "" + +#: utilities/utility.php:402 utilities/utility.php:438 +msgid "Items" +msgstr "" + +#: utilities/utility.php:403 +msgid "Description" +msgstr "" + +#: utilities/utility.php:408 +msgid "WordPress Version" +msgstr "" + +#: utilities/utility.php:412 +msgid "PHP Version" +msgstr "" + +#: utilities/utility.php:416 +msgid "PDO Support" +msgstr "" + +#: utilities/utility.php:420 +msgid "PDO Drivers" +msgstr "" + +#: utilities/utility.php:424 +msgid "PDO Driver for SQLite 3.x" +msgstr "" + +#: utilities/utility.php:428 +msgid "SQLite Library Version" +msgstr "" + +#: utilities/utility.php:434 +msgid "Your Database Status" +msgstr "" + +#: utilities/utility.php:439 +msgid "Status" +msgstr "" + +#: utilities/utility.php:445 +msgid "Database Size" +msgstr "" + +#: utilities/utility.php:449 +msgid "Page Size" +msgstr "" + +#: utilities/utility.php:453 +msgid "Total Number of Pages" +msgstr "" + +#: utilities/utility.php:457 +msgid "Unused Page" +msgstr "" + +#: utilities/utility.php:461 +msgid "Integrity Check" +msgstr "" + +#: utilities/utility.php:465 +msgid "Encoding" +msgstr "" + +#: utilities/utility.php:469 +msgid "Collations" +msgstr "" + +#: utilities/utility.php:481 +msgid "Compile Options" +msgstr "" + +#: utilities/utility.php:495 +msgid "Database Tables and Indexes" +msgstr "" + +#: utilities/utility.php:497 +msgid "" +"Table names in brown are required by WordPress, and those in blue are " +"created by some plugins. The table sqlite_sequence is not a WordPress table " +"but a table required by SQLite to store the current autoincremented value of " +"each table, which is displayed in the parenthesis after the table names. You " +"can't manipulate the tables or indexes here. Please use SQLite utilities (e." +"g. SQLiteManager)." +msgstr "" + +#: utilities/utility.php:502 +msgid "Table Name" +msgstr "" + +#: utilities/utility.php:503 +msgid "System/User" +msgstr "" + +#: utilities/utility.php:504 +msgid "Index ( Column )" +msgstr "" + +#: utilities/utility.php:529 +msgid "Plugin Info" +msgstr "" + +#: utilities/utility.php:531 +msgid "This table shows plugins you have installed and their compatibility." +msgstr "" + +#: utilities/utility.php:536 +msgid "Installed Plugins" +msgstr "" + +#: utilities/utility.php:537 +msgid "Active/Inactive" +msgstr "" + +#: utilities/utility.php:538 +msgid "Compatible" +msgstr "" + +#: utilities/utility.php:562 +msgid "Log cleared" +msgstr "" + +#: utilities/utility.php:565 +msgid "Log not cleared" +msgstr "" + +#: utilities/utility.php:577 +msgid "db.php was saved" +msgstr "" + +#: utilities/utility.php:580 +msgid "Error! db.php couldn't be saved" +msgstr "" + +#: utilities/utility.php:591 +#, php-format +msgid "" +"Optimization finished. Before optimization: %1$s, After optimization: %2$s." +msgstr "" + +#: utilities/utility.php:594 +msgid "Optimization failed" +msgstr "" + +#: utilities/utility.php:608 +msgid "Database Optimization, Error Log, Init File" +msgstr "" + +#: utilities/utility.php:609 +msgid "Optimize You Database" +msgstr "" + +#: utilities/utility.php:611 +msgid "" +"This button sends "vacuum" command to your SQLite database. That " +"command reclaims space after data has been deleted." +msgstr "" + +#: utilities/utility.php:619 +msgid "Optimize" +msgstr "" + +#: utilities/utility.php:619 +msgid "" +"Are you sure to optimize your database?\\n\\nClick [Cancel] to stop, [OK] to " +"continue." +msgstr "" + +#: utilities/utility.php:622 +msgid "SQLite Integration Error Log" +msgstr "" + +#: utilities/utility.php:624 +msgid "" +"This is the contents of SQLite Integration error log file(default: wp-content/" +"database/debug.txt). If you want to clear this file, click the Clear Log " +"button." +msgstr "" + +#: utilities/utility.php:634 +msgid "No error messages are found" +msgstr "" + +#: utilities/utility.php:642 +msgid "Clear Log" +msgstr "" + +#: utilities/utility.php:642 +msgid "" +"Are you sure to clear Log?\\n\\nClick [Cancel] to stop, [OK] to continue." +msgstr "" + +#: utilities/utility.php:646 +msgid "Edit Initial File (wp-content/db.php)" +msgstr "" + +#: utilities/utility.php:648 +msgid "" +"When you go "Plugins » Edit Plugin" page, you can edit " +"plugin source file. But you can't see this file there because it is not in " +"the plugin directory. If you need to edit this file, you can edit here. This " +"settings may cause problems. If you don't understand " +"well, please don't edit this file." +msgstr "" + +#: utilities/utility.php:658 +msgid "Save" +msgstr "" + +#: utilities/utility.php:658 +msgid "" +"Are you sure to save this file?\\n\\nClick [Cancel] to stop, [OK] to " +"continue." +msgstr "" diff --git a/pdodb.class.php b/pdodb.class.php new file mode 100644 index 0000000..e074cc7 --- /dev/null +++ b/pdodb.class.php @@ -0,0 +1,240 @@ +show_errors(); + + $this->init_charset(); + + $this->db_connect(); + } + + function __destruct() { + return true; + } + + /** + * dummy out the MySQL function + * @see wpdb::select() + */ + function select($db, $dbh = null) { + if (is_null($dbh)) + $dbh = $this->dbh; + $this->ready = true; + return; + } + + /** + * overrides wpdb::_real_escape(), which uses mysql_real_escape_string(). + * @see wpdb::_real_escape() + */ + function _real_escape($string) { + if ($this->dbh && $this->real_escape) + return $this->dbh->quote($string); + else + return addslashes($string); + } + + /** + * overrides wpdb::print_error() + * @see wpdb::print_error() + */ + function print_error($str = '') { + global $EZSQL_ERROR; + + if (!$str) { + $err = $this->dbh->get_error_message() ? $this->dbh->get_error_message() : ''; + $str = $err[2]; + } + $EZSQL_ERROR[] = array('query' => $this->last_query, 'error_str' => $str); + + if ($this->suppress_errors) + return false; + + wp_load_translations_early(); + + if ($caller = $this->get_caller()) + $error_str = sprintf(__('WordPress database error %1$s for query %2$s made by %3$s'), $str, $this->last_query, $caller); + else + $error_str = sprintf(__('WordPress database error %1$s for query %2$s'), $str, $this->last_query); + + error_log($error_str); + + if (!$this->show_errors) + return false; + + if (is_multisite()) { + $msg = "WordPress database error: [$str]\n{$this->last_query}\n"; + if (defined('ERRORLOGFILE')) + error_log($msg, 3, ERRORLOGFILE); + if (defined('DIEONDBERROR')) + wp_die($msg); + } else { + $str = htmlspecialchars($str, ENT_QUOTES); + $query = htmlspecialchars($this->last_query, ENT_QUOTES); + + print "
+

WordPress database error: [$str]
+ $query

+
"; + } + } + + /** + * overrides wpdb::db_connect() + * @see wpdb::db_connect() + */ + function db_connect() { + if (WP_DEBUG) { + $this->dbh = new PDOEngine(); + } else { + // WP_DEBUG or not, we don't use @ which causes the slow execution + // PDOEngine class will take the Exception handling. + $this->dbh = new PDOEngine(); + } + if (!$this->dbh) { + wp_load_translations_early();//probably there's no translations + $this->bail(sprintf(__("

Error establlishing a database connection

We have been unable to connect to the specified database.
The error message received was %s"), $this->dbh->errorInfo())); + return; + } + $this->ready = true; + } + + /** + * overrides wpdb::query() + * @see wpdb::query() + */ + function query($query) { + if (!$this->ready) + return false; + + $query = apply_filters('query', $query); + + $return_val = 0; + $this->flush(); + + $this->func_call = "\$db->query(\"$query\")"; + + $this->last_query = $query; + + if (defined('SAVEQUERIES') && SAVEQUERIES) + $this->timer_start(); + + $this->result = $this->dbh->query($query); + $this->num_queries++; + + if (defined('SAVEQUERIES') && SAVEQUERIES) + $this->queries[] = array($query, $this->timer_stop(), $this->get_caller()); + + if ($this->last_error = $this->dbh->get_error_message()) { + if (defined('WP_INSTALLING') && WP_INSTALLING) { + //$this->suppress_errors(); + } else { + $this->print_error($this->last_error); + return false; + } + } + + if (preg_match('/^\\s*(create|alter|truncate|drop|optimize)\\s*/i', $query)) { +// $return_val = $this->result; + $return_val = $this->dbh->get_return_value(); + } elseif (preg_match('/^\\s*(insert|delete|update|replace)\s/i', $query)) { + $this->rows_affected = $this->dbh->get_affected_rows(); + if (preg_match('/^\s*(insert|replace)\s/i', $query)) { + $this->insert_id = $this->dbh->get_insert_id(); + } + $return_val = $this->rows_affected; + } else { + $this->last_result = $this->dbh->get_query_results(); + $this->num_rows = $this->dbh->get_num_rows(); + $return_val = $this->num_rows; + } + return $return_val; + } + + /** + * overrides wpdb::load_col_info(), which uses a mysql function. + * @see wpdb::load_col_info() + */ + function load_col_info() { + if ($this->col_info) + return; + $this->col_info = $this->dbh->get_columns(); + } + + /** + * overrides wpdb::has_cap() + * We don't support collation, group_concat, set_charset + * @see wpdb::has_cap() + */ + function has_cap($db_cap) { + switch(strtolower($db_cap)) { + case 'collation': + case 'group_concat': + case 'set_charset': + return false; + case 'subqueries': + return true; + default: + return false; + } + } + /** + * overrides wpdb::db_version() + * Returns mysql version number but it means nothing for SQLite. + * @see wpdb::db_version() + */ + function db_version() { + global $required_mysql_version; + return $required_mysql_version; + } +} + +/** + * Initialize $wpdb with PDODB class + */ +if (!isset($wpdb)) { + global $wpdb; + $wpdb = new PDODB(); +} +?> \ No newline at end of file diff --git a/pdoengine.class.php b/pdoengine.class.php new file mode 100644 index 0000000..56f472c --- /dev/null +++ b/pdoengine.class.php @@ -0,0 +1,898 @@ +init(); + } + function __destruct() { + $this->pdo = null; + return true; + } + + /** + * Function to initialize database + * checks if there's a database directory and database file, creates the tables, + * and binds the user defined function to the pdo object + * @return boolean + */ + private function init() { + $dsn = 'sqlite:' . FQDB; + $result = $this->prepare_directory(); + if (!$result) return false; + if (is_file(FQDB)) { + $locked = false; + do { + try { + if ($locked) $locked = false; + $this->pdo = new PDO( + $dsn, // data source name + null, // user name + null, // user password + array( // PDO options + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION + )); + $statement = $this->pdo->query("SELECT COUNT(*) FROM sqlite_master WHERE type='table'"); + $number_of_tables = $statement->fetchColumn(0); + $statement = null; + if ($number_of_tables == 0) { + $this->make_sqlite_tables(); + } + } catch (PDOException $err) { + $status = $err->getCode(); + // code 5 => The database file is locked + // code 6 => A table in the database is locked + if ($status == 5 || $status == 6) { + $locked = true; + } else { + $message = __("Database connection error!
", 'sqlite-integration'); + $message .= sprintf(__("Error message is: ", 'sqlite-integration'), $err->getMessage()); + $this->set_error(__LINE__, __FUNCTION__, $message); + return false; + } + } + } while ($locked); + require_once UDF_FILE; + new PDOSQLiteUDFS($this->pdo); + if (version_compare($this->get_sqlite_version(), '3.7.11', '>=')) { + $this->can_insert_multiple_rows = true; + } + } else { // database file is not found, so we make it and create tables... + try { + $this->pdo = new PDO($dsn, null, null, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); + } catch (PDOException $err) { + $message = __("Database connection error!
", 'sqlite-integration'); + $message .= sprintf(__("Error message is: %s", 'sqlite-integration'), $err->getMessage()); + $this->set_error(__LINE__, __FUNCTION__, $message); + return false; + } + $this->make_sqlite_tables(); + } + } + + /** + * Make database direcotry and .htaccess file + * executed once while installation process + */ + private function prepare_directory() { + global $wpdb; + $u = umask(0000); + if (!is_dir(FQDBDIR)) { + if (!@mkdir(FQDBDIR, 0777, true)) { + umask($u); + $message = __('Unable to create the required directory! Please check your server settings.', 'sqlite-integration'); + echo $message; + return false; + } + } + if (!is_writable(FQDBDIR)) { + umask($u); + $message = __('Unable to create a file in the directory! Please check your server settings.', 'sqlite-integration'); + echo $message; + return false; + } + if (!is_file(FQDBDIR . '.htaccess')) { + $fh = fopen(FQDBDIR . '.htaccess', "w"); + if (!$fh) { + umask($u); + $message = __('Unable to create a file in the directory! Please check your server settings.', 'sqlite-integration'); + echo $message; + return false; + } + fwrite($fh, "DENY FROM ALL"); + fclose($fh); + } + umask($u); + return true; + } + /** + * Make database file itself and WordPress tables + * executed once while installation process + */ + private function make_sqlite_tables() { + require_once PDODIR . "install.php"; + } + + public function query($query) { + $this->flush(); + + $this->queries[] = "Raw query:\t$query"; + $res = $this->determine_query_type($query); + if (!$res) { + $bailoutString = sprintf(__("

Unknown query type

Sorry, we cannot determine the type of query that is requested.

The query is %s

", 'sqlite-integration'), $query); + $this->set_error(__LINE__, __FUNCTION__, $bailoutString); + } + switch (strtolower($this->query_type)) { + case 'foundrows': + $this->results = $this->found_rows_result; + $this->num_rows = count($this->results); + $this->found_rows_result = null; + break; + case 'insert': + if ($this->can_insert_multiple_rows) { + $this->execute_insert_query_new($query); + } else { + $this->execute_insert_query($query); + } + break; + case 'create': + $result = $this->execute_create_query($query); + $this->return_value = $result; + break; + case 'alter': + $result = $this->execute_alter_query($query); + $this->return_value = $result; + break; + case 'show_variables': + $result = $this->show_variables_workaround($query); + break; + default: + $engine = $this->prepare_engine($this->query_type); + $this->rewritten_query = $engine->rewrite_query($query, $this->query_type); + $this->queries[] = "Rewritten: $this->rewritten_query"; + $this->extract_variables(); + $statement = $this->prepare_query(); + $this->execute_query($statement); + if (!$this->is_error) { + $this->process_results($engine); + } else {// Error + ; + } + break; + } + if (defined('PDO_DEBUG') && PDO_DEBUG === true) { + file_put_contents(FQDBDIR . 'debug.txt', $this->get_debug_info(), FLIE_APPEND); + } + return $this->return_value; + } + + public function get_insert_id() { + return $this->last_insert_id; + } + public function get_affected_rows() { + return $this->affected_rows; + } + public function get_columns() { + return $this->column_names; + } + public function get_query_results() { + return $this->results; + } + public function get_num_rows() { + return $this->num_rows; + } + public function get_return_value() { + return $this->return_value; + } + + public function get_error_message(){ + if (count($this->error_messages) === 0){ + $this->is_error = false; + $this->error_messages = array(); + return ''; + } + $output = '
 
'; + if ($this->is_error === false){ +// return $output; + return ''; + } + $output .= "
Queries made or created this session were
\r\n\t
    \r\n"; + foreach ($this->queries as $q){ + $output .= "\t\t
  1. ".$q."
  2. \r\n"; + } + $output .= "\t
\r\n
"; + foreach ($this->error_messages as $num=>$m){ + $output .= "
Error occurred at line {$this->errors[$num]['line']} in Function {$this->errors[$num]['function']}.
Error message was: $m
"; + } + + ob_start(); + debug_print_backtrace(); + $output .= "
" . ob_get_contents() . "
"; + ob_end_clean(); + return $output; + + } + + private function get_debug_info(){ + $output = ''; + foreach ($this->queries as $q){ + $output .= $q ."\r\n"; + } + return $output; + } + + private function flush(){ + $this->rewritten_query = ''; + $this->query_type = ''; + $this->results = null; + $this->_results = null; + $this->last_insert_id = null; + $this->affected_rows = null; + $this->column_names = array(); + $this->num_rows = null; + $this->return_value = null; + $this->extracted_variables = array(); + $this->error_messages = array(); + $this->is_error = false; + $this->queries = array(); + $this->param_num = 0; + } + + private function prepare_engine($query_type = null) { + if (stripos($query_type, 'create') !== false) { + require_once PDODIR . 'query_create.class.php'; + $engine = new CreateQuery(); + } elseif (stripos($query_type, 'alter') !== false) { + require_once PDODIR . 'query_alter.class.php'; + $engine = new AlterQuery(); + } else { + require_once PDODIR . 'query.class.php'; + $engine = new PDOSQLiteDriver(); + } + return $engine; + } + + private function prepare_query(){ + $this->queries[] = "Prepare:\t". $this->prepared_query; + $reason = 0; + $message = ''; + $statement = null; + do { + try { + $statement = $this->pdo->prepare($this->prepared_query); + } catch (PDOException $err) { + $reason = $err->getCode(); + $message = $err->getMessage(); + } + } while (5 == $reason || 6 == $reason); + + if ($reason > 0){ + $err_message = sprintf(__("Problem preparing the PDO SQL Statement. Error was: %s", 'sqlite-integration'), $message); + $this->set_error(__LINE__, __FUNCTION__, $err_message); + } + return $statement; + } + + private function execute_query($statement) { + $reason = 0; + $message = ''; + if (!is_object($statement)) + return; + if (count($this->extracted_variables) > 0) { + $this->queries[] = "Executing: ". var_export($this->extracted_variables, true); + do { + if ($this->query_type == 'update' || $this->query_type == 'replace') { + try { + $this->beginTransaction(); + $statement->execute($this->extracted_variables); + $this->commit(); + } catch (PDOException $err) { + $reason = $err->getCode(); + $message = $err->getMessage(); + $this->rollBack(); + } + } else { + try { + $statement->execute($this->extracted_variables); + } catch (PDOException $err) { + $reason = $err->getCode(); + $message = $err->getMessage(); + } + } + } while (5 == $reason || 6 == $reason); + } else { + $this->queries[] = "Executing: (no parameters)\t "; + do{ + if ($this->query_type == 'update' || $this->query_type == 'replace') { + try { + $this->beginTransaction(); + $statement->execute(); + $this->commit(); + } catch (PDOException $err) { + $reason = $err->getCode(); + $message = $err->getMessage(); + $this->rollBack(); + } + } else { + try { + $statement->execute(); + } catch (PDOException $err) { + $reason = $err->getCode(); + $message = $err->getMessage(); + } + } + } while (5 == $reason || 6 == $reason); + } + if ($reason > 0) { + $err_message = sprintf(__("Error while executing query! Error message was: %s", 'sqlite-integration'), $message); + $this->set_error(__LINE__, __FUNCTION__, $err_message); + return false; + } else { + $this->_results = $statement->fetchAll(PDO::FETCH_OBJ); + } + //generate the results that $wpdb will want to see + switch ($this->query_type) { + case "insert": + case "update": + case "replace": + $this->last_insert_id = $this->pdo->lastInsertId(); + $this->affected_rows = $statement->rowCount(); + $this->return_value = $this->affected_rows; + break; + case "select": + case "show": + case "showcolumns": + case "showindex": + case "describe": + case "desc": +// case "foundrows": + $this->num_rows = count($this->_results); + $this->return_value = $this->num_rows; + break; + case "delete": + $this->affected_rows = $statement->rowCount(); + $this->return_value = $this->affected_rows; + break; + case "alter": + case "drop": + case "create": + case "optimize": + case "truncate": + if ($this->is_error) { + $this->return_value = false; + } else { + $this->return_value = true; + } + break; + } + } + + private function extract_variables() { + if ($this->query_type == 'create') { + $this->prepared_query = $this->rewritten_query; + return; + } + + //long queries can really kill this + $pattern = '/(? 10000000) { + $message = __("The query is too big to parse properly", 'sqlite-integration'); + $this->set_error(__LINE__, __FUNCTION__, $message); + break; //no point in continuing execution, would get into a loop + } else { + ini_set('pcre.backtrack_limit', $limit); + $query = preg_replace_callback($pattern, array($this,'replace_variables_with_placeholders'), $this->rewritten_query); + } + $limit = $limit * 10; + } while (empty($query)); + + //reset the pcre.backtrack_limist + ini_set('pcre.backtrack_limit', $_limit); + $this->queries[]= "With Placeholders: $query "; + $this->prepared_query = $query; + } + + private function replace_variables_with_placeholders($matches) { + //remove the wordpress escaping mechanism + $param = stripslashes($matches[0]); + + //remove trailing spaces + $param = trim($param); + + //remove the quotes at the end and the beginning + if (in_array($param{strlen($param)-1}, array("'",'"'))) { + $param = substr($param,0,-1) ;//end + } + if (in_array($param{0}, array("'",'"'))) { + $param = substr($param, 1); //start + } + //$this->extracted_variables[] = $param; + $key = ':param_'.$this->param_num++; + $this->extracted_variables[] = $param; + //return the placeholder + //return ' ? '; + return ' '.$key.' '; + } + + /** + * takes the query string ,determines the type and returns the type string + * if the query is the type PDO for Wordpress can't executes, returns false + * @param string $query + * @return boolean|string + */ + private function determine_query_type($query) { + $result = preg_match('/^\\s*(EXPLAIN|PRAGMA|SELECT\\s*FOUND_ROWS|SELECT|INSERT|UPDATE|REPLACE|DELETE|ALTER|CREATE|DROP|SHOW\\s*\\w+\\s*\\w+\\s*|DESCRIBE|DESC|TRUNCATE|OPTIMIZE)/i', $query, $match); + + if (!$result) { + return false; + } + $this->query_type = strtolower($match[1]); + if (stripos($this->query_type, 'found') !== false) { + $this->query_type = 'foundrows'; + } + if (stripos($this->query_type, 'show') !== false) { + if (stripos($this->query_type, 'show tables') !== false) { + $this->query_type = 'show'; + } elseif (stripos($this->query_type, 'show columns') !== false || stripos($this->query_type, 'show fields') !== false) { + $this->query_type = 'showcolumns'; + } elseif (stripos($this->query_type, 'show index') !== false || stripos($this->query_type, 'show indexes') !== false || stripos($this->query_type, 'show keys') !== false) { + $this->query_type = 'showindex'; + } elseif (stripos($this->query_type, 'show variables') !== false || stripos($this->query_type, 'show global variables') !== false || stripos($this->query_type, 'show session variables') !== false) { + $this->query_type = 'show_variables'; + } else { + return false; + } + } + return true; + } + + /** + * SQLite version 3.7.11 began support multiple rows insert with values + * clause. This is for that version or later. + * @param string $query + */ + private function execute_insert_query_new($query) { + $engine = $this->prepare_engine($this->query_type); + $this->rewritten_query = $engine->rewrite_query($query, $this->query_type); + $this->queries[] = "Rewritten: $this->rewritten_query"; + $this->extract_variables(); + $statement = $this->prepare_query(); + $this->execute_query($statement); + } + /** + * executes the INSERT query for SQLite version 3.7.10 or lesser + * @param string $query + */ + private function execute_insert_query($query) { + global $wpdb; + $multi_insert = false; + $statement = null; + $engine = $this->prepare_engine($this->query_type); + if (preg_match('/(INSERT.*?VALUES\\s*)(\(.*\))/imsx', $query, $matched)) { + $query_prefix = $matched[1]; + $values_data = $matched[2]; + if (stripos($values_data, 'ON DUPLICATE KEY') !== false) { + $exploded_parts = $values_data; + } elseif (stripos($query_prefix, "INSERT INTO $wpdb->comments") !== false) { + $exploded_parts = $values_data; + } else { + $exploded_parts = $this->parse_multiple_inserts($values_data); + } + $count = count($exploded_parts); + if ($count > 1) { + $multi_insert = true; + } + } + if ($multi_insert) { + $first = true; + foreach ($exploded_parts as $value) { + if (substr($value, -1, 1) === ')') { + $suffix = ''; + } else { + $suffix = ')'; + } + $query_string = $query_prefix . ' ' . $value . $suffix; + $this->rewritten_query = $engine->rewrite_query($query_string, $this->query_type); + $this->queries[] = "Rewritten: $this->rewritten_query"; + $this->extracted_variables = array(); + $this->extract_variables(); + if ($first) { + $statement = $this->prepare_query(); + $this->execute_query($statement); + $first = false; + } else { + $this->execute_query($statement); + } + } + } else { + $this->rewritten_query = $engine->rewrite_query($query, $this->query_type); + $this->queries[] = "Rewritten: $this->rewritten_query"; + $this->extract_variables(); + $statement = $this->prepare_query(); + $this->execute_query($statement); + } + } + + /** + * helper function for execute_insert_query() + * @param string $values + * @return array + */ + private function parse_multiple_inserts($values) { + $tokens = preg_split("/(''|(?prepare_engine($this->query_type); + $rewritten_query = $engine->rewrite_query($query); + $reason = 0; + $message = ''; +// $queries = explode(";", $this->rewritten_query); + try { + $this->beginTransaction(); + foreach ($rewritten_query as $single_query) { + $this->queries[] = "Executing:\t" . $single_query; + $single_query = trim($single_query); + if (empty($single_query)) continue; + $this->pdo->exec($single_query); + } + $this->commit(); + } catch (PDOException $err) { + $reason = $err->getCode(); + $message = $err->getMessage(); + if (5 == $reason || 6 == $reason) { + $this->commit(); + } else { + $this->rollBack(); + } + } + if ($reason > 0) { + $err_message = sprintf(__("Problem in creating table or index. Error was: %s", 'sqlite-integration'), $message); + $this->set_error(__LINE__, __FUNCTION__, $err_message); + return false; + } + return true; + } + + /** + * function to execute ALTER TABLE query + * @param string + * @return boolean + */ + private function execute_alter_query($query) { + $engine = $this->prepare_engine($this->query_type); + $reason = 0; + $message = ''; + $rewritten_query = $engine->rewrite_query($query, $this->query_type); + try { + $this->beginTransaction(); + if (is_array($rewritten_query)) { + foreach ($rewritten_query as $single_query) { + $this->queries[] = "Executing:\t" . $single_query; + $single_query = trim($single_query); + if (empty($single_query)) continue; + $this->pdo->exec($single_query); + } + } else { + $this->queries[] = "Executing:\t" . $rewritten_query; + $rewritten_query = trim($rewritten_query); + $this->pdo->exec($rewritten_query); + } + $this->commit(); + } catch (PDOException $err) { + $reason = $err->getCode(); + $message = $err->getMessage(); + if (5 == $reason || 6 == $reason) { + $this->commit(); + usleep(10000); + } else { + $this->rollBack(); + } + } + if ($reason > 0) { + $err_message = sprintf(__("Problem in executing alter query. Error was: %s", 'sqlite-integration'), $message); + $this->set_error(__LINE__, __FUNCTION__, $err_message); + return false; + } + return true; + } + + /** + * function to execute SHOW VARIABLES query + * + * This query is meaningless for SQLite. This function returns null data and + * avoid the error message. + * + * @param string + * @return ObjectArray + */ + private function show_variables_workaround($query) { + $dummy_data = array('Variable_name' => '', 'Value' => null); + $pattern = '/SHOW\\s*VARIABLES\\s*LIKE\\s*(.*)?$/im'; + if (preg_match($pattern, $query, $match)) { + $value = str_replace("'", '', $match[1]); + $dummy_data['Variable_name'] = trim($value); + // this is set for Wordfence Security Plugin + if ($value == 'max_allowed_packet') $dummy_data['Value'] = 1047552; + } + $_results[] = new ObjectArray($dummy_data); + $this->results = $_results; + $this->num_rows = count($this->results); + $this->return_value = $this->num_rows; + return true; + } + + private function process_results($engine) { + if (in_array($this->query_type, array('describe', 'desc', 'showcolumns'))) { + $this->convert_to_columns_object(); + } elseif ('showindex' === $this->query_type){ + $this->convert_to_index_object(); + } else { + $this->results = $this->_results; + } + } + + private function set_error ($line, $function, $message){ + global $wpdb; + $this->errors[] = array("line"=>$line, "function"=>$function); + $this->error_messages[] = $message; + $this->is_error = true; + if ($wpdb->suppress_errors) return false; + if (!$wpdb->show_errors) return false; + file_put_contents (FQDBDIR .'debug.txt', "Line $line, Function: $function, Message: $message \n", FILE_APPEND); + } + + /** + * method that takes the associative array of query results and creates a numeric array of anonymous objects + */ + private function convert_to_object(){ + $_results = array(); + if (count ($this->results) === 0){ + echo $this->get_error_message(); + } else { + foreach($this->results as $row){ + $_results[] = new ObjectArray($row); + } + } + $this->results = $_results; + } + + /** + * method to rewrite pragma results to mysql compatible array + * when query_type is describe, we use sqlite pragma function. + * see pdo_sqlite_driver.php + */ + private function convert_to_columns_object() { + $_results = array(); + $_columns = array( //Field names MySQL SHOW COLUMNS returns + 'Field' => "", + 'Type' => "", + 'Null' => "", + 'Key' => "", + 'Default' => "", + 'Extra' => "" + ); + if (count($this->_results) === 0) { + echo $this->get_error_message(); + } else { + foreach ($this->_results as $row) { + $_columns['Field'] = $row->name; + $_columns['Type'] = $row->type; + $_columns['Null'] = $row->notnull ? "NO" : "YES"; + $_columns['Key'] = $row->pk ? "PRI" : ""; + $_columns['Default'] = $row->dflt_value; + $_results[] = new ObjectArray($_columns); + } + } + $this->results = $_results; + } + /** + * rewrites the result of SHOW INDEX to the Object compatible with MySQL + */ + private function convert_to_index_object() { + $_results = array(); + $_columns = array( + 'Table' => "", + 'Non_unique' => "",// unique -> 0, not unique -> 1 + 'Key_name' => "",// the name of the index + 'Seq_in_index' => "",// column sequence number in the index. begins at 1 + 'Column_name' => "", + 'Collation' => "",//A(scend) or NULL + 'Cardinality' => "", + 'Sub_part' => "",// set to NULL + 'Packed' => "",// How to pack key or else NULL + 'Null' => "",// If column contains null, YES. If not, NO. + 'Index_type' => "",// BTREE, FULLTEXT, HASH, RTREE + 'Comment' => "" + ); + if (count($this->_results) == 0) { + echo $this->get_error_message(); + } else { + foreach ($this->_results as $row) { + if ($row->type == 'table' && !stripos($row->sql, 'primary')) + continue; + if ($row->type == 'index' && stripos($row->name, 'sqlite_autoindex') !== false) + continue; + switch ($row->type) { + case 'table': + $pattern1 = '/^\\s*PRIMARY.*\((.*)\)/im'; + $pattern2 = '/^\\s*(\\w+)?\\s*.*PRIMARY.*(?!\()/im'; + if (preg_match($pattern1, $row->sql, $match)) { + $col_name = trim($match[1]); + $_columns['Key_name'] = 'PRIMARY'; + $_columns['Non_unique'] = 0; + $_columns['Column_name'] = $col_name; + } elseif (preg_match($pattern2, $row->sql, $match)) { + $col_name = trim($match[1]); + $_columns['Key_name'] = 'PRIMARY'; + $_columns['Non_unique'] = 0; + $_columns['Column_name'] = $col_name; + } + break; + case 'index': + if (stripos($row->sql, 'unique') !== false) { + $_columns['Non_unique'] = 0; + } else { + $_columns['Non_unique'] = 1; + } + if (preg_match('/^.*\((.*)\)/i', $row->sql, $match)) { + $col_name = str_replace("'", '', $match[1]); + $_columns['Column_name'] = trim($col_name); + } + $_columns['Key_name'] = $row->name; + break; + default: + break; + } + $_columns['Table'] = $row->tbl_name; + $_columns['Collation'] = NULL; + $_columns['Cardinality'] = 0; + $_columns['Sub_part'] = NULL; + $_columns['Packed'] = NULL; + $_columns['Null'] = 'NO'; + $_columns['Index_type'] = 'BTREE'; + $_columns['Comment'] = ''; + $_results[] = new ObjectArray($_columns); + } + } + $this->results = $_results; + } + + /** + * function to get SQLite library version + * this is used for checking if SQLite can execute multiple rows insert + * @return version number string or 0 + */ + private function get_sqlite_version() { + try { + $statement = $this->pdo->prepare('SELECT sqlite_version()'); + $statement->execute(); + $result = $statement->fetch(PDO::FETCH_NUM); + return $result[0]; + } catch (PDOException $err) { + return '0'; + } + } + /** + * function call to PDO::beginTransaction() + * @see PDO::beginTransaction() + */ + public function beginTransaction() { + if ($this->has_active_transaction) { + return false; + } else { + $this->has_active_transaction = $this->pdo->beginTransaction(); + return $this->has_active_transaction; + } + } + /** + * function call to PDO::commit() + * @see PDO::commit() + */ + public function commit() { + $this->pdo->commit(); + $this->has_active_transaction = false; + } + /** + * function call to PDO::rollBack() + * @see PDO::rollBack() + */ + public function rollBack() { + $this->pdo->rollBack(); + $this->has_active_transaction = false; + } +} + +class ObjectArray { + function __construct($data = null,&$node= null) { + foreach ($data as $key => $value) { + if ( is_array($value) ) { + if (!$node) { + $node =& $this; + } + $node->$key = new stdClass(); + self::__construct($value,$node->$key); + } else { + if (!$node) { + $node =& $this; + } + $node->$key = $value; + } + } + } +} +?> \ No newline at end of file diff --git a/query.class.php b/query.class.php new file mode 100644 index 0000000..d773e9e --- /dev/null +++ b/query.class.php @@ -0,0 +1,526 @@ +query_type = $query_type; + $this->_query = $query; + switch ($this->query_type) { + case 'truncate': + $this->_handle_truncate_query(); + break; + case 'alter': + $this->_handle_alter_query(); + break; + case 'create': + $this->_handle_create_query(); + break; + case 'describe': + case 'desc': + $this->_handle_describe_query(); + break; + case 'show': + $this->_handle_show_query(); + break; + case 'showcolumns': + $this->_handle_show_columns_query(); + break; + case 'showindex': + $this->_handle_show_index(); + break; + case 'select': + $this->_strip_backticks(); + $this->_handle_sql_count(); + $this->_rewrite_date_sub(); + $this->_delete_index_hints(); + $this->_rewrite_regexp(); + $this->_rewrite_boolean(); + break; + case 'insert': + $this->_strip_backticks(); + $this->_execute_duplicate_key_update(); + $this->_rewrite_insert_ignore(); + $this->_rewrite_regexp(); + break; + case 'update': + $this->_strip_backticks(); + $this->_rewrite_update_ignore(); +// $this->_rewrite_date_sub(); + $this->_rewrite_limit_usage(); + $this->_rewrite_order_by_usage(); + $this->_rewrite_regexp(); + break; + case 'delete': + $this->_strip_backticks(); + $this->_rewrite_limit_usage(); + $this->_rewrite_order_by_usage(); + $this->_rewrite_date_sub(); + $this->_rewrite_regexp(); + $this->_delete_workaround(); + break; + case 'replace': + $this->_strip_backticks(); + $this->_rewrite_date_sub(); + $this->_rewrite_regexp(); + break; + case 'optimize': + $this->_rewrite_optimize(); + break; + default: + } + return $this->_query; + } + + /** + * method to dummy the SHOW TABLES query + */ + private function _handle_show_query(){ + $table_name = ''; + $pattern = '/^\\s*SHOW\\s*TABLES\\s*(LIKE\\s*(.*))$/im'; + if (preg_match($pattern, $this->_query, $matches)) { + $table_name = str_replace(array("'", ';'), '', $matches[2]); + } + if (!empty($table_name)) { + $suffix = ' AND name LIKE '. "'" . $table_name . "'"; + } else { + $suffix = ''; + } + $this->_query = "SELECT name FROM sqlite_master WHERE type='table'" . $suffix . ' ORDER BY name DESC'; + } + + /** + * method to strip all column qualifiers (backticks) from a query + */ + private function _strip_backticks(){ + $this->_query = str_replace('`', '', $this->_query); + } + + /** + * method to emulate the SQL_CALC_FOUND_ROWS placeholder for mysql + * + * this is a kind of tricky play. + * 1. remove SQL_CALC_FOUND_ROWS option, and give it to the pdo engine + * 2. make another $wpdb instance, and execute SELECT COUNT(*) query + * 3. give the returned value to the original instance variable + * + * when SQL statement contains GROUP BY option, SELECT COUNT query doesn't + * go well. So we remove the GROUP BY, which means the returned value may + * be a approximate one. + * + * this kind of statement is required for WordPress to calculate the paging. + * see also WP_Query class in wp-includes/query.php + */ + private function _handle_sql_count(){ + if (stripos($this->_query, 'SELECT SQL_CALC_FOUND_ROWS') !== false){ + global $wpdb; + // first strip the code. this is the end of rewriting process + $this->_query = str_ireplace('SQL_CALC_FOUND_ROWS', '', $this->_query); + // we make the data for next SELECE FOUND_ROWS() statement + $unlimited_query = preg_replace('/\\bLIMIT\\s*.*/imsx', '', $this->_query); +// $unlimited_query = preg_replace('/\\bFALSE\\s*.*/imsx', '0', $unlimited_query); + $unlimited_query = preg_replace('/\\bGROUP\\s*BY\\s*.*/imsx', '', $unlimited_query); + $unlimited_query = $this->__transform_to_count($unlimited_query); + $_wpdb = new PDODB(); + $result = $_wpdb->query($unlimited_query); + $wpdb->dbh->found_rows_result = $_wpdb->last_result; + } + } + + /** + * transforms a select query to a select count(*) + * + * @param string $query the query to be transformed + * @return string the transformed query + */ + private function __transform_to_count($query){ + $pattern = '/^\\s*SELECT\\s*(DISTINCT|)?.*?FROM\b/imsx'; + $_query = preg_replace($pattern, 'SELECT \\1 COUNT(*) FROM ', $query); + return $_query; + } + + /** + * rewrites the insert ignore phrase for sqlite + */ + private function _rewrite_insert_ignore(){ + $this->_query = str_ireplace('INSERT IGNORE', 'INSERT OR IGNORE ', $this->_query); + } + + /** + * rewrites the update ignore phrase for sqlite + */ + private function _rewrite_update_ignore(){ + $this->_query = str_ireplace('UPDATE IGNORE', 'UPDATE OR IGNORE ', $this->_query); + } + + + /** + * rewrites the date_add function for udf to manipulate + */ + private function _rewrite_date_add(){ + //(date,interval expression unit) + $pattern = '/\\s*date_add\\s*\(([^,]*),([^\)]*)\)/imsx'; + if (preg_match($pattern, $this->_query, $matches)) { + $expression = "'".trim($matches[2])."'"; + $this->_query = preg_replace($pattern, " date_add($matches[1], $expression) ", $this->_query); + } + } + + /** + * rewrite the data_sub function for udf to manipulate + */ + private function _rewrite_date_sub(){ + //(date,interval expression unit) + $pattern = '/\\s*date_sub\\s*\(([^,]*),([^\)]*)\)/imsx'; + if (preg_match($pattern, $this->_query, $matches)) { + $expression = "'".trim($matches[2])."'"; + $this->_query = preg_replace($pattern, " date_sub($matches[1], $expression) ", $this->_query); + } + } + + /** + * handles the create query + * this function won't be used... See PDOEngine class + */ + private function _handle_create_query(){ + require_once PDODIR.'query_create.class.php'; + $engine = new CreateQuery(); + $this->_query = $engine->rewrite_query($this->_query); + $engine = null; + } + + /** + * handles the ALTER query + * this function won't be used... See PDOEngine class + */ + private function _handle_alter_query(){ + require_once PDODIR . 'query_alter.class.php'; + $engine = new AlterQuery(); + $this->_query = $engine->rewrite_query($this->_query, 'alter'); + $engine = null; + } + + /** + * handles DESCRIBE or DESC query + * this is required in the WordPress install process + */ + private function _handle_describe_query(){ + // $this->_query = "select 1=1"; + $pattern = '/^\\s*(DESCRIBE|DESC)\\s*(.*)/i'; + if (preg_match($pattern, $this->_query, $match)) { + $tablename = preg_replace('/[\';]/', '', $match[2]); + $this->_query = "PRAGMA table_info($tablename)"; + } + } + + /** + * The author of the original 'PDO for WordPress' says update method of wpdb + * insists on adding LIMIT. But the newest version of WordPress doesn't do that. + * Nevertheless some plugins use DELETE with LIMIT, UPDATE with LIMIT. + * We need to exclude sub query's LIMIT. + */ + private function _rewrite_limit_usage(){ + if (stripos($this->_query, '(select') === false) { + $this->_query = preg_replace('/\\s*LIMIT\\s*[0-9]$/i', '', $this->_query); + } + } + /** + * SQLite compiled without SQLITE_ENABLE_UPDATE_DELETE_LIMIT option can't + * execute UPDATE with ORDER BY, DELETE with GROUP BY. + * We need to exclude sub query's GROUP BY. + */ + private function _rewrite_order_by_usage() { + if (stripos($this->_query, '(select') === false) { + $this->_query = preg_replace('/\\s*ORDER\\s*BY\\s*.*$/i', '', $this->_query); + } + } + + private function _handle_truncate_query(){ + $pattern = '/TRUNCATE TABLE (.*)/im'; + $this->_query = preg_replace($pattern, 'DELETE FROM $1', $this->_query); + } + /** + * rewrites use of Optimize queries in mysql for sqlite. + * table name is ignored. + */ + private function _rewrite_optimize(){ + $this->_query ="VACUUM"; + } + + /** + * Jusitn Adie says: some wp UI interfaces (notably the post interface) + * badly composes the day part of the date leading to problems in sqlite + * sort ordering etc. + * + * I don't understand that... + * + * @return void + */ + private function _rewrite_badly_formed_dates(){ + $pattern = '/([12]\d{3,}-\d{2}-)(\d )/ims'; + $this->_query = preg_replace($pattern, '${1}0$2', $this->_query); + } + + /** + * function to remove unsupported index hinting from mysql queries + * + * @return void + */ + private function _delete_index_hints(){ + $pattern = '/use\s+index\s*\(.*?\)/i'; + $this->_query = preg_replace($pattern, '', $this->_query); + } + + /** + * Justin Adie says: + * method to fix inconsistent use of quoted, unquoted etc date values in query function + * this is ironic, given the above rewrite badlyformed dates method + * examples + * where month(fieldname)=08 becomes month(fieldname)='8' + * where month(fieldname)='08' becomes month(fieldname)='8' + * + * I don't understand... + * + * @return void + */ + private function _fix_date_quoting(){ + $pattern = '/(month|year|second|day|minute|hour|dayofmonth)\s*\((.*?)\)\s*=\s*["\']?(\d{1,4})[\'"]?\s*/ei'; + $this->_query = preg_replace($pattern, "'\\1(\\2)=\'' . intval('\\3') . '\' ' ", $this->_query); + } + + private function _rewrite_regexp(){ + $pattern = '/\s([^\s]*)\s*regexp\s*(\'.*?\')/im'; + $this->_query = preg_replace($pattern, ' regexpp(\1, \2)', $this->_query); + } + + /** + * rewrites boolean to numeral + * SQLite doesn't support true/false type + */ + private function _rewrite_boolean() { + $query = str_ireplace('TRUE', "1", $this->_query); + $query = str_ireplace('FALSE', "0", $query); + $this->_query = $query; + } + + /** + * method to execute SHOW COLUMNS query + */ + private function _handle_show_columns_query() { + $pattern_like = '/^\\s*SHOW\\s*(COLUMNS|FIELDS)\\s*FROM\\s*(.*)?\\s*LIKE\\s*(.*)?/i'; + $pattern = '/^\\s*SHOW\\s*(COLUMNS|FIELDS)\\s*FROM\\s*(.*)?/i'; + if (preg_match($pattern_like, $this->_query, $matches)) { + $table_name = str_replace("'", "", trim($matches[2])); + $column_name = str_replace("'", "", trim($matches[3])); + $query_string = "SELECT sql FROM sqlite_master WHERE tbl_name='$table_name' AND sql LIKE '%$column_name%'"; + $this->_query = $query_string; + } elseif (preg_match($pattern, $this->_query, $matches)) { + $table_name = $matches[2]; + $query_string = preg_replace($pattern, "PRAGMA table_info($table_name)", $this->_query); + $this->_query = $query_string; + } + } + + /** + * method to execute SHOW INDEX query + */ + private function _handle_show_index() { + $_columns = array(// No, you'll get no meaningful information.. + 'Key_name' => 'name', + ); + $pattern_0 = '/^\\s*SHOW\\s*(?:INDEX|INDEXES|KEYS)\\s*FROM\\s*(\\w+)?\\s*WHERE\\s*(.*)$/im'; + $pattern_1 = '/^\\s*SHOW\\s*(?:INDEX|INDEXES|KEYS)\\s*FROM\\s*(\\w+)?/im'; + if (preg_match($pattern_0, $this->_query, $match_0)) { + $table_name = str_replace("'", '', $match_0[1]); + list($key, $value) = explode('=', $match_0[2]); + $key = trim($key); + $value = preg_replace("/[\';]/", '', $value); + $value = trim($value); + if (array_key_exists($key, $_columns)) { + $key = $_columns[$key]; + $where_clause = 'AND ' . $key . ' LIKE ' . "'" . $value . "%'"; + } else { + $where_clause = ''; + } + $this->_query = "SELECT * FROM sqlite_master WHERE tbl_name='$table_name' $where_clause"; + } elseif (preg_match($pattern_1, $this->_query, $match_1)) { + $table_name = preg_replace("/[\';]/", '', $match_1[1]); + $table_name = trim($table_name); + $this->_query = "SELECT * FROM sqlite_master WHERE tbl_name='$table_name'"; + } + } + + /** + * function to rewrite ON DUPLICATE KEY UPDATE statement + * I use SELECT query and check if INSERT is allowed or not + * Rewriting procedure looks like a detour, but I've got another way. + * + * @return void + */ + private function _execute_duplicate_key_update() { + $update = false; + $unique_keys_for_cond = array(); + $unique_keys_for_check = array(); + $pattern = '/^\\s*INSERT\\s*INTO\\s*(\\w+)?\\s*(.*)\\s*ON\\s*DUPLICATE\\s*KEY\\s*UPDATE\\s*(.*)$/ims'; + if (preg_match($pattern, $this->_query, $match_0)) { + $table_name = trim($match_0[1]); + $insert_data = trim($match_0[2]); + $update_data = trim($match_0[3]); + // prepare two unique key data for the table + // 1. array('col1', 'col2, col3', etc) 2. array('col1', 'col2', 'col3', etc) + $_wpdb = new PDODB(); + $indexes = $_wpdb->get_results("SHOW INDEX FROM {$table_name}"); + if (!empty($indexes)) { + foreach ($indexes as $index) { + if ($index->Non_unique == 0) { + $unique_keys_for_cond[] = $index->Column_name; + if (strpos($index->Column_name, ',') !== false) { + $unique_keys_for_check = array_merge($unique_keys_for_check, explode(',', $index->Column_name)); + } else { + $unique_keys_for_check[] = $index->Column_name; + } + } + } + $unique_keys_for_check = array_map('trim', $unique_keys_for_check); + } else { + // Without unique key or primary key, UPDATE statement will affect all the rows! + $query = 'INSERT INTO '.$table_name.' '.$insert_data; + $this->_query = $query; + $_wpdb = null; + return; + } + // data check + if (preg_match('/^\((.*)\)\\s*VALUES\\s*\((.*)\)$/im', $insert_data, $match_1)) { + $col_array = explode(',', $match_1[1]); + $ins_data_array = explode(',', $match_1[2]); + foreach ($col_array as $col) { + $val = trim(array_shift($ins_data_array)); + $ins_data_assoc[trim($col)] = $val; + } +// $ins_data_assoc = array_combine($col_array, $ins_array); + $condition = ''; + foreach ($unique_keys_for_cond as $unique_key) { + if (strpos($unique_key, ',') !== false) { + $unique_key_array = explode(',', $unique_key); + $counter = count($unique_key_array); + for ($i = 0; $i < $counter; ++$i) { + $col = trim($unique_key_array[$i]); + if (isset($ins_data_assoc[$col]) && $i == $counter - 1) { + $condition .= $col . '=' . $ins_data_assoc[$col] . ' OR '; + } elseif (isset($ins_data_assoc[$col])) { + $condition .= $col . '=' . $ins_data_assoc[$col] . ' AND '; + } else { + continue; + } + } +// $condition = rtrim($condition, ' AND '); + } else { + $col = trim($unique_key); + if (isset($ins_data_assoc[$col])) { + $condition .= $col . '=' . $ins_data_assoc[$col] . ' OR '; + } else { + continue; + } + } + } + $condition = rtrim($condition, ' OR '); + $test_query = "SELECT * FROM {$table_name} WHERE {$condition}"; + $results = $_wpdb->query($test_query); + $_wpdb = null; + if ($results == 0) { + $this->_query = 'INSERT INTO '.$table_name.' '.$insert_data; + return; + } else { + // change (col, col...) values (data, data...) to array(col=>data, col=>data...) + if (preg_match('/^\((.*)\)\\s*VALUES\\s*\((.*)\)$/im', $insert_data, $match_2)) { + $col_array = explode(',', $match_2[1]); + $ins_array = explode(',', $match_2[2]); + $count = count($col_array); + for ($i = 0; $i < $count; $i++) { + $col = trim($col_array[$i]); + $val = trim($ins_array[$i]); + $ins_array_assoc[$col] = $val; + } + } + // change col = data, col = data to array(col=>data, col=>data) + // some plugins have semi-colon at the end of the query + $update_data = rtrim($update_data, ';'); + $tmp_array = explode(',', $update_data); + foreach ($tmp_array as $pair) { + list($col, $value) = explode('=', $pair); + $col = trim($col); + $value = trim($value); + $update_array_assoc[$col] = $value; + } + // change array(col=>values(col)) to array(col=>data) + foreach ($update_array_assoc as $key => &$value) { + if (preg_match('/^VALUES\\s*\((.*)\)$/im', $value, $match_3)) { + $col = trim($match_3[1]); + $value = $ins_array_assoc[$col]; + } + } + foreach ($ins_array_assoc as $key => $val) { + if (in_array($key, $unique_keys_for_check)) { + $where_array[] = $key . '=' . $val; + } + } + $update_strings = ''; + foreach ($update_array_assoc as $key => $val) { + if (in_array($key, $unique_keys_for_check)) { + $where_array[] = $key . '=' . $val; + } else { + $update_strings .= $key . '=' . $val . ','; + } + } + $update_strings = rtrim($update_strings, ','); + $unique_where = array_unique($where_array, SORT_REGULAR); + $where_string = ' WHERE ' . implode(' AND ', $unique_where); + // $where_string = ' WHERE ' . rtrim($where_string, ','); + $update_query = 'UPDATE ' . $table_name . ' SET ' . $update_strings . $where_string; + $this->_query = $update_query; + } + } + } else { + // wordaround... + $pattern = '/ ON DUPLICATE KEY UPDATE.*$/im'; + $replace_query = preg_replace($pattern, '', $this->_query); + $replace_query = str_ireplace('INSERT ', 'INSERT OR REPLACE ', $replace_query); + $this->_query = $replace_query; + } + } + + /** + * workaround function to avoid DELETE with JOIN + * wp-admin/includes/upgrade.php contains 'DELETE ... JOIN' statement. + * This query can't be replaced with regular expression or udf, so we + * replace all the statement with another. + */ + private function _delete_workaround() { + global $wpdb; +// $pattern = "DELETE o1 FROM $wpdb->options AS o1 JOIN $wpdb->options AS o2 USING (option_name) WHERE o2.option_id > o1.option_id"; + $pattern = "DELETE o1 FROM $wpdb->options AS o1 JOIN $wpdb->options AS o2"; + $rewritten = "DELETE FROM $wpdb->options WHERE option_id IN (SELECT MIN(option_id) FROM $wpdb->options GROUP BY option_name HAVING COUNT(*) > 1)"; + if (stripos($this->_query, $pattern) !== false) { + $this->_query = $rewritten; + } + } +} +?> \ No newline at end of file diff --git a/query_alter.class.php b/query_alter.class.php new file mode 100644 index 0000000..0b410a6 --- /dev/null +++ b/query_alter.class.php @@ -0,0 +1,453 @@ +split_multiple($command); + foreach ($command_array as $single_command) { + $command_tokens = $this->command_tokenizer($single_command); + if (!empty($command_tokens)) { + $tokens[] = array_merge($tmp_tokens, $command_tokens); + } else { + $this->_query = 'SELECT 1=1'; + } + } + foreach ($tokens as $token) { + $command_name = $token['command']; + switch ($command_name) { + case 'add column': case 'rename to': case 'add index': case 'drop index': + $this->_query = $this->handle_single_command($token); + break; + case 'add primary key': + $this->_query = $this->handle_add_primary_key($token); + break; + case 'drop primary key': + $this->_query = $this->handle_drop_primary_key($token); + break; + case 'modify column': + $this->_query = $this->handle_modify_command($token); + break; + case 'change column': + $this->_query = $this->handle_change_command($token); + break; + case 'alter column': + $this->_query = $this->handle_alter_command($token); + break; + default: + break; + } + } + } else { + $this->_query = 'SELECT 1=1'; + } + return $this->_query; + } + + private function command_tokenizer($command) { + $tokens = array(); + if (preg_match('/^(ADD|DROP|RENAME|MODIFY|CHANGE|ALTER)\\s*(\\w+)?\\s*(\\w+)?\\s*/ims', $command, $match)) { + $the_rest = str_ireplace($match[0], '', $command); + $match_1 = strtolower(trim($match[1])); + $match_2 = strtolower(trim($match[2])); + $match_3 = isset($match[3]) ? strtolower(trim($match[3])) : ''; + switch ($match_1) { + case 'add': + if (in_array($match_2, array('fulltext', 'constraint', 'foreign'))) { + break; + } elseif ($match_2 == 'column') { + $tokens['command'] = $match_1.' '.$match_2; + $tokens['column_name'] = $match_3; + $tokens['column_def'] = trim($the_rest); + } elseif ($match_2 == 'primary') { + $tokens['command'] = $match_1.' '.$match_2.' '.$match_3; + $tokens['column_name'] = $the_rest; + } elseif ($match_2 == 'unique') { + list($index_name, $col_name) = preg_split('/[\(\)]/s', trim($the_rest), -1, PREG_SPLIT_DELIM_CAPTURE); + $tokens['unique'] = true; + $tokens['command'] = $match_1.' '.$match_3; + $tokens['index_name'] = trim($index_name); + $tokens['column_name'] = '('.trim($col_name).')'; + } elseif (in_array($match_2, array('index', 'key'))) { + $tokens['command'] = $match_1.' '.$match_2; + $tokens['index_name'] = $match_3; + $tokens['column_name'] = trim($the_rest); + } else { + $tokens['command'] = $match_1.' column'; + $tokens['column_name'] = $match_2; + $tokens['column_def'] = $match_3.' '.$the_rest; + } + break; + case 'drop': + if ($match_2 == 'column') { + $tokens['command'] = $match_1.' '.$match_2; + $tokens['column_name'] = trim($match_3); + } elseif ($match_2 == 'primary') { + $tokens['command'] = $match_1.' '.$match_2.' '.$match_3; + } elseif (in_array($match_2, array('index', 'key'))) { + $tokens['command'] = $match_1.' '.$match_2; + $tokens['index_name'] = $match_3; + } elseif ($match_2 == 'primary') { + $tokens['command'] = $match_1.' '.$match_2.' '.$match_3; + } else { + $tokens['command'] = $match_1.' column'; + $tokens['column_name'] = $match_2; + } + break; + case 'rename': + if ($match_2 == 'to') { + $tokens['command'] = $match_1.' '.$match_2; + $tokens['column_name'] = $match_3; + } else { + $tokens['command'] = $match_1.' to'; + $tokens['column_name'] = $match_2; + } + break; + case 'modify': + if ($match_2 == 'column') { + $tokens['command'] = $match_1.' '.$match_2; + $tokens['column_name'] = $match_3; + $tokens['column_def'] = trim($the_rest); + } else { + $tokens['command'] = $match_1.' column'; + $tokens['column_name'] = $match_2; + $tokens['column_def'] = $match_3.' '.trim($the_rest); + } + break; + case 'change': + if ($match_2 == 'column') { + $tokens['command'] = $match_1.' '.$match_2; + $tokens['old_column'] = $match_3; + list($new_col) = preg_split('/\s/s', trim($the_rest), -1, PREG_SPLIT_DELIM_CAPTURE); + $tokens['new_column'] = $new_col; + $col_def = str_ireplace($new_col, '', $the_rest); + $tokens['column_def'] = trim($col_def); + } else { + $tokens['command'] = $match_1.' column'; + $tokens['old_column'] = $match_2; + $tokens['new_column'] = $match_3; + $tokens['column_def'] = trim($the_rest); + } + break; + case 'alter': + if ($match_2 == 'column') { + $tokens['command'] = $match_1.' '.$match_2; + $tokens['column_name'] = $match_3; + list($set_or_drop) = explode(' ', $the_rest); + if ($set_or_drop == 'set') { + $tokens['default_command'] = 'set default'; + $default_value = str_ireplace('set default', '', $the_rest); + $tokens['default_value'] = trim($default_value); + } else { + $tokens['default_command'] = 'drop default'; + } + } else { + $tokens['command'] = $match_1.' column'; + $tokens['column_name'] = $match_2; + if ($match_3 == 'set') { + $tokens['default_command'] = 'set default'; + $default_value = str_ireplace('default', '', $the_rest); + $tokens['default_value'] = trim($default_value); + } else { + $tokens['default_command'] = 'drop default'; + } + } + break; + default: + break; + } + return $tokens; + } + } + + private function split_multiple($command) { + $out = true; + $command_array = array(); + $command_string = ''; + $tokens = preg_split('/\b/s', $command, -1, PREG_SPLIT_DELIM_CAPTURE); + foreach ($tokens as $token) { + switch (trim($token)) { + case ';': + break; + case '(': + $command_string .= $token; + $out = false; + break; + case ')': + $command_string .= $token; + $out = true; + break; + case '),': + $command_array[] = $command_string; + $command_string = ''; + $out = true; + break; + case ',': + if ($out) { + $command_array[] = $command_string; + $command_string = ''; + } else { + $command_string .= $token; + } + break; + default: + $command_string .= $token; + break; + } + } + if (!empty($command_string)) { + $command_array[] = $command_string; + } + return $command_array; + } + + private function handle_single_command($queries) { + $tokenized_query = $queries; + if (stripos($tokenized_query['command'], 'add column') !== false) { + $column_def = $this->convert_field_types($tokenized_query['column_name'], $tokenized_query['column_def']); + $query = "ALTER TABLE {$tokenized_query['table_name']} ADD COLUMN {$tokenized_query['column_name']} $column_def"; + } elseif (stripos($tokenized_query['command'], 'rename') !== false) { + $query = "ALTER TABLE {$tokenized_query['table_name']} RENAME TO {$tokenized_query['column_name']}"; + } elseif (stripos($tokenized_query['command'], 'add index') !== false) { + $unique = isset($tokenized_query['unique']) ? 'UNIQUE' : ''; + $query = "CREATE $unique INDEX IF NOT EXISTS {$tokenized_query['index_name']} ON {$tokenized_query['table_name']} {$tokenized_query['column_name']}"; + } elseif (stripos($tokenized_query['command'], 'drop index') !== false) { + $query = "DROP INDEX IF EXISTS {$tokenized_query['index_name']}"; + } else { + $query = 'SELECT 1=1'; + } + return $query; + } + + private function handle_add_primary_key($queries) { + $tokenized_query = $queries; + $tbl_name = $tokenized_query['table_name']; + $temp_table = 'temp_'.$tokenized_query['table_name']; + $_wpdb = new PDODB(); + $query_obj = $_wpdb->get_results("SELECT sql FROM sqlite_master WHERE tbl_name='$tbl_name'"); + $_wpdb = null; + for ($i = 0; $i < count($query_obj); $i++) { + $index_queries[$i] = $query_obj[$i]->sql; + } + $table_query = array_shift($index_queries); + $table_query = str_replace($tokenized_query['table_name'], $temp_table, $table_query); + $table_query = rtrim($table_query, ')'); + $table_query = ", PRIMARY KEY {$tokenized_query['column_name']}"; + $query[] = $table_query; + $query[] = "INSERT INTO $temp_table SELECT * FROM {$tokenized_query['table_name']}"; + $query[] = "DROP TABLE IF EXISTS {$tokenized_query['table_name']}"; + $query[] = "ALTER TABLE $temp_table RENAME TO {$tokenized_query['table_name']}"; + foreach ($index_queries as $index) { + $query[] = $index; + } + return $query; + } + + private function handle_drop_primary_key($queries) { + $tokenized_query = $queries; + $temp_table = 'temp_'.$tokenized_query['table_name']; + $_wpdb = new PDODB(); + $query_obj = $_wpdb->get_results("SELECT sql FROM sqlite_master WHERE tbl_name='{$tokenized_query['table_name']}'"); + $_wpdb = null; + for ($i = 0; $i < count($query_obj); $i++) { + $index_queries[$i] = $query_obj[$i]->sql; + } + $table_query = array_shift($index_queries); + $pattern1 = '/^\\s*PRIMARY\\s*KEY\\s*\(.*\)/im'; + $pattern2 = '/^\\s*.*(PRIMARY\\s*KEY\\s*(:?AUTOINCREMENT|))\\s*(?!\()/im'; + if (preg_match($pattern1, $table_query, $match)) { + $table_query = str_replace($match[0], '', $table_query); + } elseif (preg_match($pattern2, $table_query, $match)) { + $table_query = str_replace($match[1], '', $table_query); + } + $table_query = str_replace($tokenized_query['table_name'], $temp_table, $table_query); + $query[] = $table_query; + $query[] = "INSERT INTO $temp_table SELECT * FROM {$tokenized_query['table_name']}"; + $query[] = "DROP TABLE IF EXISTS {$tokenized_query['table_name']}"; + $query[] = "ALTER TABLE $temp_table RENAME TO {$tokenized_query['table_name']}"; + foreach ($index_queries as $index) { + $query[] = $index; + } + return $query; + } + + private function handle_modify_command($queries) { + $tokenized_query = $queries; + $temp_table = 'temp_'.$tokenized_query['table_name']; + $column_def = $this->convert_field_types($tokenized_query['column_name'], $tokenized_query['column_def']); + $_wpdb = new PDODB(); + $query_obj = $_wpdb->get_results("SELECT sql FROM sqlite_master WHERE tbl_name='{$tokenized_query['table_name']}'"); + $_wpdb = null; + for ($i =0; $i < count($query_obj); $i++) { + $index_queries[$i] = $query_obj[$i]->sql; + } + $create_query = array_shift($index_queries); + if (stripos($create_query, $tokenized_query['column_name']) === false) { + return 'SELECT 1=1'; + } elseif (preg_match("/{$tokenized_query['column_name']}\\s*{$tokenized_query['column_def']}\\s*[,)]/i", $create_query)) { + return 'SELECT 1=1'; + } + $create_query = preg_replace("/{$tokenized_query['table_name']}/i", $temp_table, $create_query); + if (preg_match("/\\b{$tokenized_query['column_name']}\\s*.*(?=,)/ims", $create_query)) { + $create_query = preg_replace("/\\b{$tokenized_query['column_name']}\\s*.*(?=,)/ims", "{$tokenized_query['column_name']} {$tokenized_query['column_def']}", $create_query); + } elseif (preg_match("/\\b{$tokenized_query['column_name']}\\s*.*(?=\))/ims", $create_query)) { + $create_query = preg_replace("/\\b{$tokenized_query['column_name']}\\s*.*(?=\))/ims", "{$tokenized_query['column_name']} {$tokenized_query['column_def']}", $create_query); + } + $query[] = $create_query; + $query[] = "INSERT INTO $temp_table SELECT * FROM {$tokenized_query['table_name']}"; + $query[] = "DROP TABLE IF EXISTS {$tokenized_query['table_name']}"; + $query[] = "ALTER TABLE $temp_table RENAME TO {$tokenized_query['table_name']}"; + foreach ($index_queries as $index) { + $query[] = $index; + } + return $query; + } + + private function handle_change_command($queries) { + $col_check = false; + $old_fields = ''; + $new_fields = ''; + $tokenized_query = $queries; + $temp_table = 'temp_'.$tokenized_query['table_name']; + $column_def = $this->convert_field_types($tokenized_query['new_column'], $tokenized_query['column_def']); + $_wpdb = new PDODB(); + $col_obj = $_wpdb->get_results("SHOW COLUMNS FROM {$tokenized_query['table_name']}"); + foreach ($col_obj as $col) { + if ($col->Field == $tokenized_query['old_column']) $col_check = true; + $old_fields .= $col->Field . ','; + } + if ($col_check == false) { + $_wpdb = null; + return 'SELECT 1=1'; + } + $old_fields = rtrim($old_fields, ','); + $new_fields = str_replace($tokenized_query['old_column'], $tokenized_query['new_column'], $old_fields); + $query_obj = $_wpdb->get_results("SELECT sql FROM sqlite_master WHERE tbl_name='{$tokenized_query['table_name']}'"); + $_wpdb = null; + for ($i = 0; $i < count($query_obj); $i++) { + $index_queries[$i] = $query_obj[$i]->sql; + } + $create_query = array_shift($index_queries); + $create_query = preg_replace("/{$tokenized_query['table_name']}/i", $temp_table, $create_query); + if (preg_match("/\\b{$tokenized_query['old_column']}\\s*(.+?)(?=,)/ims", $create_query, $match)) { + if ($tokenized_query['column_def'] == trim($match[1])) { + return 'SELECT 1=1'; + } else { + $create_query = preg_replace("/\\b{$tokenized_query['old_column']}\\s*.*?(?=,)/ims", "{$tokenized_query['new_column']} {$tokenized_query['column_def']}", $create_query); + } + } elseif (preg_match("/\\b{$tokenized_query['old_column']}\\s*(.+?)(?=\))/ims", $create_query, $match)) { + if ($tokenized_query['column_def'] == trim($match[1])) { + return 'SELECT 1=1'; + } else { + $create_query = preg_replace("/\\b{$tokenized_query['old_column']}\\s*.*?(?=\))/ims", "{$tokenized_query['new_column']} {$tokenized_query['column_def']}", $create_query); + } + } + $query[] = $create_query; + $query[] = "INSERT INTO $temp_table ($new_fields) SELECT $old_fields FROM {$tokenized_query['table_name']}"; + $query[] = "DROP TABLE IF EXISTS {$tokenized_query['table_name']}"; + $query[] = "ALTER TABLE $temp_table RENAME TO {$tokenized_query['table_name']}"; + foreach ($index_queries as $index) { + $query[] = $index; + } + return $query; + } + + private function handle_alter_command($queries) { + $tokenized_query = $queries; + $temp_table = 'temp_'.$tokenized_query['table_name']; + if (stripos($tokenized_query['default_command'], 'set') !== false) { + $def_value = $this->convert_field_types($tokenized_query['column_name'], $tokenized_query['default_value']); + $def_value = 'DEFAULT '.$def_value; + } else { + $def_value = ''; + } + $_wpdb = new PDODB(); + $query_obj = $_wpdb->get_results("SELECT sql FROM sqlite_master WHERE tbl_name='{$tokenized_query['table_name']}'"); + $_wpdb = null; + for ($i =0; $i < count($query_obj); $i++) { + $index_queries[$i] = $query_obj[$i]->sql; + } + $create_query = array_shift($index_queries); + if (stripos($create_query, $tokenized_query['column_name']) === false) { + return 'SELECT 1=1'; + } + if (preg_match("/\\s*({$tokenized_query['column_name']}\\s*.*?)\\s*(DEFAULT\\s*.*)[,)]/im", $create_query, $match)) { + $col_def = trim($match[1]); + $old_default = trim($match[2]); + $create_query = preg_replace("/($col_def)\\s*$old_default/im", "\\1 $def_value", $create_query); + $create_query = str_ireplace($tokenized_query['table_name'], $temp_table, $create_query); + } else { + return 'SELECT 1=1'; + } + $query[] = $create_query; + $query[] = "INSERT INTO $temp_table SELECT * FROM {$tokenized_query['table_name']}"; + $query[] = "DROP TABLE IF EXISTS {$tokenized_query['table_name']}"; + $query[] = "ALTER TABLE $temp_table RENAME TO {$tokenized_query['table_name']}"; + foreach ($index_queries as $index) { + $query[] = $index; + } + return $query; + } + /** + * Change the field definition to SQLite compatible data type. + * @param string $col_name + * @param string $col_def + * @return string + */ + private function convert_field_types($col_name, $col_def){ + $array_types = array( + 'bit' => 'INTEGER', 'bool' => 'INTEGER', + 'boolean' => 'INTEGER', 'tinyint' => 'INTEGER', + 'smallint' => 'INTEGER', 'mediumint' => 'INTEGER', + 'int' => 'INTEGER', 'integer' => 'INTEGER', + 'bigint' => 'INTEGER', 'float' => 'REAL', + 'double' => 'REAL', 'decimal' => 'REAL', + 'dec' => 'REAL', 'numeric' => 'REAL', + 'fixed' => 'REAL', 'date' => 'TEXT', + 'datetime' => 'TEXT', 'timestamp' => 'TEXT', + 'time' => 'TEXT', 'year' => 'TEXT', + 'char' => 'TEXT', 'varchar' => 'TEXT', + 'binary' => 'INTEGER', 'varbinary' => 'BLOB', + 'tinyblob' => 'BLOB', 'tinytext' => 'TEXT', + 'blob' => 'BLOB', 'text' => 'TEXT', + 'mediumblob' => 'BLOB', 'mediumtext' => 'TEXT', + 'longblob' => 'BLOB', 'longtext' => 'TEXT' + ); + $array_curtime = array('current_timestamp', 'current_time', 'current_date'); + $array_reptime = array("'0000-00-00 00:00:00'", "'0000-00-00 00:00:00'", "'0000-00-00'"); + $def_string = str_replace('`', '', $col_def); + foreach ($array_types as $o=>$r){ + $pattern = "/\\b" . $o . "\\s*(\([^\)]*\))?\\s*/imsx"; + if (preg_match($pattern, $def_string)) { + $def_string = preg_replace($pattern, "$r ", $def_string); + break; + } + } + $def_string = preg_replace('/unsigned/im', '', $def_string); + $def_string = preg_replace('/auto_increment/im', 'PRIMARY KEY AUTOINCREMENT', $def_string); + // when you use ALTER TABLE ADD, you can't use current_*. so we replace + $def_string = str_ireplace($array_curtime, $array_reptime, $def_string); + // colDef is enum + $pattern_enum = '/enum\((.*?)\)([^,\)]*)/ims'; + if (preg_match($pattern_enum, $col_def, $matches)) { + $def_string = 'TEXT' . $matches[2] . ' CHECK (' . $col_name . ' IN (' . $matches[1] . '))'; + } + return $def_string; + } +} +?> \ No newline at end of file diff --git a/query_create.class.php b/query_create.class.php new file mode 100644 index 0000000..35b5df0 --- /dev/null +++ b/query_create.class.php @@ -0,0 +1,285 @@ +_query = $query; + $this->_errors [] = ''; + $this->strip_backticks(); + $this->get_table_name(); + $this->rewrite_comments(); + $this->rewrite_field_types(); + $this->rewrite_character_set(); + $this->rewrite_engine_info(); + $this->rewrite_unsigned(); + $this->rewrite_autoincrement(); + $this->rewrite_primary_key(); + $this->rewrite_unique_key(); + $this->rewrite_enum(); + $this->rewrite_set(); + $this->rewrite_key(); + $this->add_if_not_exists(); + + return $this->post_process(); + } + + /** + * Method for getting the table name from the create query. + * taken from PDO for WordPress + * we don't need 'IF NOT EXISTS', so we changed the pattern. + */ + private function get_table_name(){ + // $pattern = '/^\\s*CREATE\\s*(TEMP|TEMPORARY)?\\s*TABLE\\s*(IF NOT EXISTS)?\\s*([^\(]*)/imsx'; + $pattern = '/^\\s*CREATE\\s*(?:TEMP|TEMPORARY)?\\s*TABLE\\s*(?:IF\\s*NOT\\s*EXISTS)?\\s*([^\(]*)/imsx'; + if (preg_match($pattern, $this->_query, $matches)) { + $this->table_name = trim($matches[1]); + } + } + + /** + * Method for changing the field type to SQLite compatible type. + */ + private function rewrite_field_types(){ + $array_types = array ( + 'bit' => 'integer', 'bool' => 'integer', + 'boolean' => 'integer', 'tinyint' => 'integer', + 'smallint' => 'integer', 'mediumint' => 'integer', + 'int' => 'integer', 'integer' => 'integer', + 'bigint' => 'integer', 'float' => 'real', + 'double' => 'real', 'decimal' => 'real', + 'dec' => 'real', 'numeric' => 'real', + 'fixed' => 'real', 'date' => 'text', + 'datetime' => 'text', 'timestamp' => 'text', + 'time' => 'text', 'year' => 'text', + 'char' => 'text', 'varchar' => 'text', + 'binary' => 'integer', 'varbinary' => 'blob', + 'tinyblob' => 'blob', 'tinytext' => 'text', + 'blob' => 'blob', 'text' => 'text', + 'mediumblob' => 'blob', 'mediumtext' => 'text', + 'longblob' => 'blob', 'longtext' => 'text' + ); + foreach ($array_types as $o=>$r){ + $pattern = '/\\b(?_query = preg_replace($pattern, " $r ", $this->_query); + } + } + + /** + * Method for stripping the comments from the SQL statement + */ + private function rewrite_comments(){ + $this->_query = preg_replace("/# --------------------------------------------------------/","-- ******************************************************",$this->_query); + $this->_query = preg_replace("/#/","--",$this->_query); + } + + /** + * Method for stripping the engine and other stuffs + */ + private function rewrite_engine_info(){ + $this->_query = preg_replace("/\\s*(TYPE|ENGINE)\\s*=\\s*.*(?_query); + $this->_query = preg_replace("/ AUTO_INCREMENT\\s*=\\s*[0-9]*/ims",'',$this->_query); + } + + /** + * Method for stripping unsigned + */ + private function rewrite_unsigned(){ + $this->_query = preg_replace('/\\bunsigned\\b/ims', ' ', $this->_query); + } + + /** + * Method for rewriting auto_increment + * if the field type is 'integer primary key', it is automatically autoincremented + */ + private function rewrite_autoincrement(){ + $this->_query = preg_replace('/\\bauto_increment\\s*primary\\s*key\\s*(,)?/ims', ' PRIMARY KEY AUTOINCREMENT \\1', $this->_query, -1, $count); + $this->_query = preg_replace('/\\bauto_increment\\b\\s*(,)?/ims', ' PRIMARY KEY AUTOINCREMENT $1', $this->_query, -1, $count); + if ($count > 0){ + $this->has_primary_key = true; + } + } + + /** + * Method for rewriting primary key + */ + private function rewrite_primary_key(){ + if ($this->has_primary_key) { + $this->_query = preg_replace('/\\bprimary key\\s*\([^\)]*\)/ims', ' ', $this->_query); + } else { + // If primary key has an index name, we remove that name. + $this->_query = preg_replace('/\\bprimary\\s*key\\s*.*?\\s*(\(.*?\))/im', 'PRIMARY KEY \\1', $this->_query); + } + } + + /** + * Method for rewriting unique key + */ + private function rewrite_unique_key(){ + $this->_query = preg_replace_callback('/\\bunique key\\b([^\(]*)(\([^\)]*\))/ims', array($this, '_rewrite_unique_key'), $this->_query); + } + + /** + * Callback method for rewrite_unique_key + * @param array $matches an array of matches from the Regex + */ + private function _rewrite_unique_key($matches){ + $index_name = trim($matches[1]); + $col_name = trim($matches[2]); + $tbl_name = $this->table_name; + $_wpdb = new PDODB(); + $results = $_wpdb->get_results("SELECT name FROM sqlite_master WHERE type='index'"); + $_wpdb = null; + if ($results) { + foreach ($results as $result) { + if ($result->name == $index_name) { + $r = rand(0, 50); + $index_name = $index_name . "_$r"; + break; + } + } + } + $index_name = str_replace(' ', '', $index_name); + $this->index_queries[] = "CREATE UNIQUE INDEX $index_name ON " . $tbl_name .$col_name; + return ''; + } + + /** + * Method for handling ENUM fields + * SQLite doesn't support enum, so we change it to check constraint + */ + private function rewrite_enum(){ + $pattern = '/(,|\))([^,]*)enum\((.*?)\)([^,\)]*)/ims'; + $this->_query = preg_replace_callback($pattern, array($this, '_rewrite_enum'), $this->_query); + } + + /** + * Method for the callback function rewrite_enum and rewrite_set + */ + private function _rewrite_enum($matches){ + $output = $matches[1] . ' ' . $matches[2]. ' TEXT '. $matches[4].' CHECK ('.$matches[2].' IN ('.$matches[3].')) '; + return $output; + } + + /** + * Method for rewriting usage of set + * whilst not identical to enum, they are similar and sqlite does not + * support either. + */ + private function rewrite_set(){ + $pattern = '/\b(\w)*\bset\\s*\((.*?)\)\\s*(.*?)(,)*/ims'; + $this->_query = preg_replace_callback($pattern, array($this, '_rewrite_enum'), $this->_query); + } + + /** + * Method for rewriting usage of key to create an index + * sqlite cannot create non-unique indices as part of the create query + * so we need to create an index by hand and append it to the create query + */ + private function rewrite_key(){ + $this->_query = preg_replace_callback('/,\\s*(KEY|INDEX)\\s*(\\w+)?\\s*(\(.*(?_query); + } + + /** + * Callback method for rewrite_key + * @param array $matches an array of matches from the Regex + */ + private function _rewrite_key($matches){ + $index_name = trim($matches[2]); + $col_name = trim($matches[3]); + if (preg_match('/\([0-9]+?\)/', $col_name, $match)) { + $col_name = preg_replace_callback('/\([0-9]+?\)/', array($this, '_remove_length'), $col_name); + } + $tbl_name = $this->table_name; + $_wpdb = new PDODB(); + $results = $_wpdb->get_results("SELECT name FROM sqlite_master WHERE type='index'"); + $_wpdb = null; + if ($results) { + foreach ($results as $result) { + if ($result->name == $index_name) { + $r = rand(0, 50); + $index_name = $index_name . "_$r"; + break; + } + } + } + $this->index_queries[] = 'CREATE INDEX '. $index_name . ' ON ' . $tbl_name . $col_name ; + return ''; + } + private function _remove_length($match) { + return ''; + } + /** + * Method to assemble the main query and index queries into an array + * to be returned to the base class + * @return array + */ + private function post_process(){ + $mainquery = $this->_query; + do{ + $count = 0; + $mainquery = preg_replace('/,\\s*\)/imsx',')', $mainquery, -1, $count); + } while ($count > 0); + do { + $count = 0; + $mainquery = preg_replace('/\(\\s*?,/imsx', '(', $mainquery, -1, $count); + } while ($count > 0); + $return_val[] = $mainquery; + $return_val = array_merge($return_val, $this->index_queries); + return $return_val; + } + /** + * Method to add IF NOT EXISTS to query defs + * sometimes, if upgrade.php is being called, wordpress seems to want to run + * new create queries. this stops the query from throwing an error and halting + * output + */ + private function add_if_not_exists(){ + $pattern_table = '/^\\s*CREATE\\s*(TEMP|TEMPORARY)?\\s*TABLE\\s*(IF NOT EXISTS)?\\s*/ims'; + $this->_query = preg_replace($pattern_table, 'CREATE $1 TABLE IF NOT EXISTS ', $this->_query); + $pattern_index = '/^\\s*CREATE\\s*(UNIQUE)?\\s*INDEX\\s*(IF NOT EXISTS)?\\s*/ims'; + for ($i = 0; $i < count($this->index_queries); $i++) { + $this->index_queries[$i] = preg_replace($pattern_index, 'CREATE $1 INDEX IF NOT EXISTS ', $this->index_queries[$i]); + } + } + + /** + * Method to strip back ticks + */ + private function strip_backticks(){ + $this->_query = str_replace('`', '', $this->_query); + foreach ($this->index_queries as &$query) { + $query = str_replace('`', '', $query); + } + } + + /** + * Method to remove the character set information from within mysql queries + */ + private function rewrite_character_set(){ + $pattern_charset = '/\\b(default\\s*character\\s*set|default\\s*charset|character\\s*set)\\s*(?_query = preg_replace($patterns, '', $this->_query); + } +} \ No newline at end of file diff --git a/readme-ja.txt b/readme-ja.txt new file mode 100644 index 0000000..d8ceb27 --- /dev/null +++ b/readme-ja.txt @@ -0,0 +1,170 @@ +=== SQLite Integration === +Contributors: kjmtsh +Plugin Name: SQLite Integration +Plugin URI: http://dogwood.skr.jp/wordpress/sqlite-integration-ja/ +Tags: database, SQLite, PDO +Author: Kojima Toshiyasu +Author URI: http://dogwood.skr.jp/ +Requires at least: 3.3 +Tested up to: 3.5.2 +Stable tag: 1.0 +License: GPLv2 +License URI: http://www.gnu.org/licenses/gpl-2.0.html + +SQLite IntegrationはSQLiteでWordPressを使えるようにするプラグインです。 + +== Description == + +このプラグインは[SQLite](http://www.sqlite.org/)を使ってWordPressを運用するためのものです。MySQLデータベース・サーバを用意する必要はありません。SQLiteは自己完結的で、サーバを必要とせず、トランザクションをサポートしたデータベース・エンジンです。MySQLのようにたくさんの拡張機能を持たないかわりに、小規模から中規模のトラフィックがあるウェブサイトに適しています。 + +SQLite Integrationはラッパ・プログラムです。WordPressとSQLiteの間に入って、やり取りを中継し、次のように動作します。 + +1. WordPressからMySQLに発行されるSQLステートメントをインターセプトします +2. それをSQLiteが実行できる形に書き換えます +3. SQLiteに渡します +4. SQLiteから結果を受け取ります +5. 必要なら、WordPressが望む形式にフォーマットしなおします +6. WordPressに結果を返します + +WordPressはMySQLと話していると思っていて、背後で何が起こっているかは知りません。実際にはSQLiteと話しているのですが、WordPressはいつもの通り仕事をします。 + +SQLite Integrationは[PDO for WordPress](http://wordpress.org/extend/plugins/pdo-for-wordpress)プラグインの後継です。後者は残念なことに、もうメンテナンスされていないようです。SQLite IntegrationはPDO for WordPressの基本的なアイディアと構造を借りて、より多くの機能とユーティリティを追加しました。 + += Features = + +SQLite Integrationは普通の「プラグイン」ではありません。WordPressをインストールするときに使います。そのため、少し準備が必要です。インストールのセクションを参照してください。[SQLite Integration Page](http://dogwood.skr.jp/wordpress/sqlite-integration/)をご覧になると、もっと詳しい説明を読むことができます。 + +インストールに成功したら、MySQLを使う他のWordPressと同じように使うことができます。オプションとして、管理パネルでこのプラグインを有効化することができます。有効化すると有益な情報と説明を見ることができます。これは必須ではありませんが、お勧めします。 + += Backward Compatibility = + +現在[PDO for WordPress](http://wordpress.org/extend/plugins/pdo-for-wordpress)をお使いの場合は、データベースを移行することができます。インストールのセクションをご覧ください。 + += Support = + +下の方法でコンタクトを取ってください。 + +[Support Forum](http://wordpress.org/support/plugin/sqlite-integration)にポストする。 + +注意: WordPress.orgはMySQL以外のデータベースを正式にサポートしていません。だから、WordPress.orgからのサポートは得られません。フォーラムに投稿しても、回答を得ることはまずないでしょう。また、パッチをあてたプラグインを使う場合は、そのプラグインの作者からのサポートはないものと思ってください。自分でリスクを負う必要があります。 + += Translation = + +ドキュメントは英語で書かれています。日本語のカタログファイルと、.potファイルがアーカイブに含まれています。もしあなたの言語に翻訳をしたら、知らせてください。 + +== Installation == + +このプラグインは他のプラグインとはちがいます。管理パネルのプラグイン・ページでインストールすることはできません。 + +まず、WordPressのインストールを準備しなければなりません。Codexの[Installing Wordpress ](http://codex.wordpress.org/Installing_WordPress)をご覧ください。 + +必要要件をチェックし、WordPressのアーカイブを展開したら、wp-config-sample.phpをwp-config.phpにリネームして、[Codex page](http://codex.wordpress.org/Editing_wp-config.php)に書いてあるように、少し編集する必要があります。データベースの設定*以外*の部分を設定してください。 + +終わったら、オプションの設定を書き加えることができます。次の説明に従ってください。 + +* デフォルト(wp-content/database)とは違うディレクトリにSQLiteデータベース・ファイルを置きたい場合は、次の行を追加してください(最後のスラッシュを忘れずに)。 + + `define('DB_DIR', '/home/youraccount/database_directory/');` + + 注意: PHPスクリプトがこのディレクトリを作ったり、中にファイルを書き込んだりする権限を持っていることが必要です。 + +* デフォルト(.ht.sqlite)とは違うデータベース・ファイル名を使いたい場合は、次の行を追加してください。 + + `define('DB_FILE', 'database_file_name');` + + 注意: PDO for WordPressをお使いの方は、「データベースを移行する」のセクションをご覧ください。 + + よくわからない場合は、何も追加する必要はありません。 + +wp-config.phpの準備が終わったら、次のステップに進みます。 + +1. プラグインのアーカイブを展開します。 + +2. アーカイブに含まれるdb.phpファイルをwp-contentディレクトリに移動(またはコピー)してください。 + +3. sqlite-wordpressディレクトリをwp-content/plugin/ディレクトリの下に移動してください。 + + `wordpress/wp-contents/db.php` + + と、 + + `wordpress/wp-contents/sqlite-integration` + + のようになります。 + +さあ、これでお終いです。ディレクトリの構造をそのままに、あなたのサーバにアップロードして、お好きなブラウザでwp-admin/install.phpにアクセスしてください。WordPressのインストールが始まります。Enjoy blogging! + += Migrate your database to SQLite Integration = + +一番よい方法は、次のようにすることです。 + +1. データをエクスポートする。 + +2. 最新のWordPressを、SQLite Integrationを使って新規インストールする。 + +3. WordPress Importerを使って以前のデータをインポートする。 + +何らかの理由で、データがエクスポートできない場合は、次の方法を試すことができます。 + +1. あなたのMyBlog.sqliteがWordPressの必要とするテーブルを全て含んでいるかどうかチェックしてください。[SQLite Manager Mozilla Addon](https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/)のようなユーティリティが必要かもしれません。また、Codexの[Database Description](http://codex.wordpress.org/Database_Description)を参照してください。 + +2. MyBlog.sqliteとdb.phpファイルをバックアップしてください。 + +3. あなたのMyBlog.sqliteを.ht.sqliteにリネームするか、または、wp-config.phpに次の行を追加してください。 + + `define('FQDB', 'MyBlog.sqlite');` + +4. wp-content/db.phpをSQLite Integrationに含まれている同名のファイルと入れ替えてください。 + +これでおしまいです。忘れずに必要要件とWordPressのバージョンをチェックしてください。*SQLite IntegrationはWordPress 3.2.x以前のものでは動作しません。* + +== Frequently Asked Questions == + += データベース・ファイルが作られません = + +ディレクトリやファイルを作るのに失敗するのは、多くの場合、PHPにその権限がないことが原因です。サーバの設定を確認するか、管理者に聞いてみてください。 + += あれこれのプラグインが有効化できません、あるいはちゃんと動作しません = + +ある種のプラグイン、特にキャッシュ系のプラグインやデータベース管理系のプラグインはこのプラグインと一緒に使えません。SQLite Integrationを有効化して、ドキュメントの「プラグイン互換性」のセクションをご覧ください。あるいは、[SQLite Integration Plugin Page](http://dogwood.skr.jp/wordpress/plugins/)をご覧ください。 + += 管理画面のドキュメントは必要ないのですが = + +無効化すればすぐに消えます。有効化と無効化は管理画面の表示・非表示だけで、本体には影響を与えません。プラグインを削除したい場合は、単に削除すれば消えます。 + +== Screenshots == + +1. システム情報の画面ではデータベースの状態やプラグインの対応状況を見ることができます。 + +== Requirements == + +* PHP 5.2 以上で PDO extension が必要です(PHP 5.3 以上をお勧めします)。 +* PDO SQLite ドライバがロードされている必要があります。 + +== Known Limitations == + +多くのプラグインはちゃんと動作するはずです。が、中にはそうでないものもあります。一般的には、WordPressの関数を通さず、PHPのMysqlあるいはMysqliライブラリの関数を使ってデータベースを操作しようとするプラグインは問題を起こすでしょう。 + +他には下のようなものがあります。 + += これらのプラグインを使うことはできません。SQLite Integrationと同じファイルを使おうとするからです。 = + +* [W3 Total Cache](http://wordpress.org/extend/plugins/w3-total-cache/) +* [DB Cache Reloaded Fix](http://wordpress.org/extend/plugins/db-cache-reloaded-fix/) +* [HyperDB](http://wordpress.org/extend/plugins/hyperdb/) + += これらのプラグインも使えません。SQLiteがエミュレートできないMySQL独自の拡張機能を使っているからです。 = + +* [Yet Another Related Posts](http://wordpress.org/extend/plugins/yet-another-related-posts-plugin/) +* [Better Related Posts](http://wordpress.org/extend/plugins/better-related/) + +たぶん、もっとあるでしょう。 + +== Changelog == + += 1.0 (2013-07-07) = +最初のリリース。 + +== Upgrade Notice == + +SQLite Integrationのアップグレードに失敗するようなら、FTPを使っての手動アップグレードを試してみてください。 diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..967e6d9 --- /dev/null +++ b/readme.txt @@ -0,0 +1,162 @@ +=== SQLite Integration === +Contributors: kjmtsh +Plugin Name: SQLite Integration +Plugin URI: http://dogwood.skr.jp/wordpress/sqlite-integration/ +Tags: database, SQLite, PDO +Author: Kojima Toshiyasu +Author URI: http://dogwood.skr.jp/ +Requires at least: 3.3 +Tested up to: 3.5.2 +Stable tag: 1.0 +License: GPLv2 +License URI: http://www.gnu.org/licenses/gpl-2.0.html + +SQLite Integration is the plugin that enables WordPress to use SQLite. If you want to build a WordPress website with it, this plugin is for you. + +== Description == + +This plugin enables WordPress to work with [SQLite](http://www.sqlite.org/). You don't have to prepare MySQL database server and its configuration. SQLite is a self-contained, serverless, transactional SQL database engine. It is not a full-featured database system like MySQL or PostgreSQL, but it best fits for low to medium traffic websites. + +SQLite Integration is a kind of wrapper program, which is placed between WordPress and SQLite database and works as a mediator. It works as follows: + +1. Intercepts the SQL statement for MySQL from WordPress +2. Rewrites it for SQLite to execute +3. Give it to SQLite +4. Gets the results from SQLite +5. Formats the results as WordPress wants, if necessary +6. Give the results back to WordPress + +WordPress thinks she talks with MySQL and doesn't know what has happened in the background. She really talks with SQLite and will be happy with it. + +SQLite Integration is a successor to [PDO for WordPress](http://wordpress.org/extend/plugins/pdo-for-wordpress) plugin, which unfortunately enough, doesn't seem to be maintained any more. SQLite Integration uses the basic idea and structures of that plugin and adds some more features or some utilities. + += Features = + +SQLite Integration is not an ordinary 'plugin'. It is used to install WordPress itself. You need to do some preparations. Please read the install section. And see more detailed instruction in the [SQLite Integration Page](http://dogwood.skr.jp/wordpress/sqlite-integration). + +Once you succeeded in installing WordPress, you can use it just like the others using MySQL. Optionally, you can activate this plugin in the installed plugins panel of the adimn dashboard, and you can see the useful information and instructions. It is not required but I recommend it. + += Backward Compatibility = + +If you are using [PDO for WordPress](http://wordpress.org/extend/plugins/pdo-for-wordpress), you can migrate your database. See install section. + += Support = + +Please contact us with the methods below: + +Post to [Support Forum](http://wordpress.org/support/plugin/sqlite-integration/). + +Notes: WordPress.org doesn't officially support using any other database than MySQL. So there will be no supports from WordPress.org. Even if you post to the general Forum, you have few chances to get the answer. And if you use patched plugins, you will have be no support from the plugin authors, eithter. + += Translation = + +Documentation is written in English. Japanese catalog file and .pot file are included in the archive. If you translate it into your language, please let me know. + +== Installation == + +This plugin is *not* like the other plugins. You can't install and activate it on the plugin administration panel. + +First of all, you've got to prepare WordPress installation. See [Installing Wordpress ](http://codex.wordpress.org/Installing_WordPress) section in the Codex. + +After checking the prerequisites and unzipping the WordPress archive file, you must rename wp-contig-sample.php file to wp-config.php and do some editting as the [Codex page](http://codex.wordpress.org/Editing_wp-config.php) says. Please follow the instructions *except* the database settings. + +When you finish, you can add optional settings. Follow the steps below: + +* If you want to put the SQLite database file to the directory different from the default setting (wp-content/database), you can add the line below (don't forget to add a trailing slash): + + `define('DB_DIR', '/home/youraccount/database_directory/');` + + Note: Your PHP scripts must be able to create that directory and files in it. + +* If you want to change the database file name to the one different from the default (.ht.sqlite), you can add the line below: + + `define('DB_FILE', 'database_file_name');` + + Note: If you are using 'PDO for WordPress' plugin, see also 'Migrating your database' section. + + If you don't understand well, you don't have to add any of the lines above. + +After you finish preparing wp-config.php, follow the next steps: + +1. Unzip the plugin archive file. + +2. Move db.php file contained in the archive to wp-content directory. + +3. Move the sqlite-integration directory to wp-content/plugin/ directory. + + `wordpress/wp-contents/db.php` + + and + + `wordpress/wp-contents/sqlite-integration` + + respectively. + +OK. This is all. Upload everything (keeping the directory structure) to your server and access the wp-admin/install.php with your favorite browser, and WordPress installation process will begin. Enjoy your blogging! + += Migrate your database to SQLite Integration = + +If you are using PDO for WordPress now, you can migrate your database to SQLite Integration. You don't have to reinstall WordPress. Please follow the next steps: + +1. Check if your MyBlog.sqlite file contains all the tables required by WordPress. You have to use a utility software like [SQLite Manager Mozilla Addon](https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/). See also [Database Description](http://codex.wordpress.org/Database_Description) in Codex. + +2. Backup your MyBlog.sqlite and db.php files. + +3. EITHER rename your MyBlog.sqlite to .ht.sqlite OR add the next line in wp-config.php file. + + `define('FQDB', 'MyBlog.sqlite');` + +4. Overwrite your wp-content/db.php with the db.php file contained in SQLite Integration archive. + +That's all. Don't forget to check the requirement and your WordPress version. *SQLite Integration doesn't work with WordPress version 3.2.x or lesser*. + +== Frequently Asked Questions == + += Database file is not created = + +The reason of failure in creating directory or files is often that PHP is not allowed to craete them. Please check your server setting or ask the administrator. + += Such and such plugins can't be activated or doesn't seem to work properly = + +Some of the plugins, especially cache plugins or database maintenace plugins, are not compatible with this plugin. Please activate SQLite Integration and see the plugin comatibility section in the documentation or visit the [SQLite Integration Page](http://dogwood.skr.jp/wordpress/sqlite-integration/). + += I don't want the admin menu and documentation = + +Just deactivate the plugin, and you can remove them. Activation and deactivation affect only admin menu. If you want to remove all the plugin files, just delete it. + +== Screenshots == + +1. System Information tells you your database status and installed plugins compatibility. + +== Requirements == + +* PHP 5.2 or newer with PDO extension (PHP 5.3 or newer is better). +* PDO SQLite driver must be loaded. + +== Known Limitations == + +Many of the other plugins will work fine with this plugin. But there are some you can't use. Generally speaking, the plugins that manipulate database not with WordPress functions but with Mysql or Mysqli native drivers from PHP might cause the problem. + +These are other examples: + += You can't use these plugins because they create the same file that this plugin uses: = + +* [W3 Total Cache](http://wordpress.org/extend/plugins/w3-total-cache/) +* [DB Cache Reloaded Fix](http://wordpress.org/extend/plugins/db-cache-reloaded-fix/) +* [HyperDB](http://wordpress.org/extend/plugins/hyperdb/) + += You can't use some of the plugins, because they are using MySQL specific features that SQLite can't emulate. For example: = + +* [Yet Another Related Posts](http://wordpress.org/extend/plugins/yet-another-related-posts-plugin/) +* [Better Related Posts](http://wordpress.org/extend/plugins/better-related/) + +Probably there are more, I'm afraid. + +== Changelog == + += 1.0 (2013-07-07) = +First release version of the plugin. + +== Upgrade Notice == + +When you fail in upgrading SQLite Integration, I recommend that you should try manual upgrade via FTP. diff --git a/schema.php b/schema.php new file mode 100644 index 0000000..dec5a59 --- /dev/null +++ b/schema.php @@ -0,0 +1,91 @@ + PDO::ERRMODE_EXCEPTION)); + } catch (PDOException $err) { + $err_data = $err->errorInfo; + $message = __("Database connection error!
", 'sqlite-integration'); + $message .= sprintf(__("Error message is: %s", 'sqlite-integration'), $err_data[2]); + echo $message; + return false; + } + + try { + $pdo->beginTransaction(); + foreach ($queries as $query) { + $query = trim($query); + if (empty($query)) + continue; + $rewritten_query = $query_parser->rewrite_query($query); + if (is_array($rewritten_query)) { + $table_query = array_shift($rewritten_query); + $index_queries = $rewritten_query; + $table_query = trim($table_query); + $pdo->exec($table_query); +// foreach($rewritten_query as $single_query) { +// $single_query = trim($single_query); +// $pdo->exec($single_query); +// } + } else { + $rewritten_query = trim($rewritten_query); + $pdo->exec($rewritten_query); + } + } + $pdo->commit(); + if ($index_queries) { + // $query_parser rewrites KEY to INDEX, so we don't need KEY pattern + $pattern = '/CREATE\\s*(UNIQUE\\s*INDEX|INDEX)\\s*IF\\s*NOT\\s*EXISTS\\s*(\\w+)?\\s*.*/im'; + $pdo->beginTransaction(); + foreach ($index_queries as $index_query) { + preg_match($pattern, $index_query, $match); + $index_name = trim($match[2]); + if (in_array($index_name, $index_array)) { + $r = rand(0, 50); + $replacement = $index_name . "_$r"; + $index_query = str_ireplace('EXISTS '.$index_name, 'EXISTS '.$replacement, $index_query); + } else { + $index_array[] = $index_name; + } + $pdo->exec($index_query); + } + $pdo->commit(); + } + } catch (PDOException $err) { + $err_data = $err->errorInfo; + $err_code = $err_data[1]; + if (5 == $err_code || 6 == $err_code) { + // if the database is locked, commit again + $pdo->commit(); + } else { + $pdo->rollBack(); + $message = sprintf(__("Error occured while creating tables or indexes...
Query was: %s
", 'sqlite-integration'), var_export($rewritten_query, true)); + $message .= sprintf(__("Error message is: %s", 'sqlite-integration'), $err_data[2]); + echo $message; + return false; + } + } + + $query_parser = null; + $pdo = null; + return true; +} +?> \ No newline at end of file diff --git a/screenshots-1.png b/screenshots-1.png new file mode 100644 index 0000000000000000000000000000000000000000..07e3e359f006aff5e0f7e6231857620a4c24bfac GIT binary patch literal 89858 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

9r?P{&V!rOz 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 literal 0 HcmV?d00001 diff --git a/sqlite-integration.php b/sqlite-integration.php new file mode 100644 index 0000000..fa292b0 --- /dev/null +++ b/sqlite-integration.php @@ -0,0 +1,238 @@ +blogid; + $blog_ids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs"); + foreach ($blog_ids as $blog_id) { + switch_to_blog($blog_id); + $this->_install(); + } + switch_to_blog($old_blog); + return; + } else { + $this->_install(); + return; + } + } + + /** + * Nothing to do... + * We show menu and documents only to the network administrator + */ + function _install() { + } + + /** + * Is it better that we remove wp-content/db.php and wp-content/patches + * directory?... + * If you migrate the site to the sever with MySQL, you have only to + * migrate the data in the database. + */ + function uninstall() { + // remove patch files and patch directory + if (file_exists(SQLitePatchDir) && is_dir(SQLitePatchDir)) { + $dir_handle = opendir(SQLitePatchDir); + while (($file_name = readdir($dir_handle)) !== false) { + if ($file_name != '.' && $file_name != '..') { + unlink(SQLitePatchDir.'/'.$file_name); + } + } + rmdir(SQLitePatchDir); + } + // remove wp-content/db.php + if (defined('WP_CONTENT_DIR')) { + $target = WP_CONTENT_DIR . 'db.php'; + } else { + $target = ABSPATH . 'wp-content/db.php'; + } + if (file_exists($target)) { + unlink($target); + } + } + + /** + * We use class method to show pages and want to load style files and script + * files only in our plugin documents, so we need add_submenu_page with parent + * slug set to null. This means that menu items are added but hidden from the + * users. + */ + function add_pages() { + global $utils, $doc, $patch_utils; + if (function_exists('add_options_page')) { + $welcome_page = add_options_page(__('SQLite Integration'), __('SQLite Integration'), 'manage_options', 'sqlite-integration', array($utils, 'welcome')); + $util_page = add_submenu_page(null, 'System Info', 'System Info', 'manage_options', 'sys-info', array($utils, 'show_utils')); + $edit_db = add_submenu_page(null, 'Setting File', 'Setting File', 'manage_options', 'setting-file', array($utils, 'edit_db_file')); + $doc_page = add_submenu_page(null, 'Documentation', 'Documentation', 'manage_options', 'doc', array($doc, 'show_doc')); + $patch_page = add_submenu_page(null, 'Patch Utility', 'Patch Utility', 'manage_options', 'patch', array($patch_utils, 'show_patch_page')); + add_action('admin_print_styles-'.$welcome_page, array($this, 'add_style_sheet')); + add_action('admin_print_styles-'.$util_page, array($this, 'add_style_sheet')); + add_action('admin_print_styles-'.$edit_db, array($this, 'add_style_sheet')); + add_action('admin_print_styles-'.$doc_page, array($this, 'add_doc_style_sheet')); + add_action('admin_print_styles-'.$patch_page, array($this, 'add_style_sheet')); + add_action('admin_print_scripts-'.$util_page, array($this, 'add_sqlite_script')); + add_action('admin_print_scripts-'.$doc_page, array($this, 'add_sqlite_script')); + add_action('admin_print_scripts-'.$patch_page, array($this, 'add_sqlite_script')); + } + } + + /** + * Network admin can only see documents and manipulate patch files. + * So, capability is set to manage_network_options. + */ + function add_network_pages() { + global $utils, $doc, $patch_utils; + if (function_exists('add_options_page')) { + $welcome_page = add_submenu_page('settings.php', __('SQLite Integration'), __('SQLite Integration'), 'manage_network_options', 'sqlite-integration', array($utils, 'welcome')); + $util_page = add_submenu_page(null, 'System Info', 'System Info', 'manage_network_options', 'sys-info', array($utils, 'show_utils')); + $edit_db = add_submenu_page(null, 'Setting File', 'Setting File', 'manage_network_options', 'setting-file', array($utils, 'edit_db_file')); + $doc_page = add_submenu_page(null, 'Documentation', 'Documentation', 'manage_network_options', 'doc', array($doc, 'show_doc')); + $patch_page = add_submenu_page(null, 'Patch Utility', 'Patch Utility', 'manage_network_options', 'patch', array($patch_utils, 'show_patch_page')); + add_action('admin_print_styles-'.$welcome_page, array($this, 'add_style_sheet')); + add_action('admin_print_styles-'.$util_page, array($this, 'add_style_sheet')); + add_action('admin_print_styles-'.$edit_db, array($this, 'add_style_sheet')); + add_action('admin_print_styles-'.$doc_page, array($this, 'add_doc_style_sheet')); + add_action('admin_print_styles-'.$patch_page, array($this, 'add_style_sheet')); + add_action('admin_print_scripts-'.$util_page, array($this, 'add_sqlite_script')); + add_action('admin_print_scripts-'.$doc_page, array($this, 'add_sqlite_script')); + add_action('admin_print_scripts-'.$patch_page, array($this, 'add_sqlite_script')); + } + } + + /** + * Japanese catalog is only available + */ + function textdomain_init() { + global $utils; +// $current_locale = get_locale(); +// if (!empty($current_locale)) { +// $moFile = dirname(__FILE__) . "/languages/sqlite-wordpress-" . $current_locale . ".mo"; +// if(@file_exists($moFile) && is_readable($moFile)) load_textdomain('sqlite-wordpress', $moFile); +// } + load_plugin_textdomain($utils->text_domain, false, SQLiteDir.'/languages/'); + } + + /** + * Styles and JavaScripts + */ + function add_style_sheet() { + $style_url = SQLiteUrl . '/styles/style.css'; + $style_file = SQLiteFilePath . '/styles/style.css'; + if (file_exists($style_file)) { + wp_enqueue_style('sqlite_integration_stylesheet', $style_url); + } + } + function add_doc_style_sheet() { + $style_url = SQLiteUrl . '/styles/doc.css'; + $style_file = SQLiteFilePath . '/styles/doc.css'; + if (file_exists($style_file)) { + wp_enqueue_style('sqlite_integration_doc_style', $style_url); + } + } + function add_sqlite_script() { + $script_url = SQLiteUrl . '/js/sqlite.js'; + $script_file = SQLiteFilePath . '/js/sqlite.js'; + if (file_exists($script_file)) { + wp_enqueue_script('sqlite-integration', $script_url, 'jquery'); + } + } +} + +/* this is enough for initialization */ +new SQLiteIntegration; +?> \ No newline at end of file diff --git a/styles/doc.css b/styles/doc.css new file mode 100644 index 0000000..c3255b0 --- /dev/null +++ b/styles/doc.css @@ -0,0 +1,141 @@ +@CHARSET "UTF-8"; +#sqlite-admin-wrap h2, +#sqlite-admin-side-wrap h2 { + background: rgb(73, 90, 88); + background: -moz-linear-gradient(bottom, rgba(73, 90, 88, 1), rgba(73, 90, 88, 0.5), rgba(73, 90, 88, 0)); + background: -webkit-gradient(linear, bottom, top, from(rgba(73, 90, 88, 1)), color-stop(0.5, rgba(73, 90, 88, 0.5)), to(rgba(73, 90, 88, 0))); + background: linear-gradient(to top, rgba(73, 90, 88, 1), rgba(73, 90, 88, 0.2)); + color: rgb(247, 254, 236); + -webkit-border-top-right-radius: 6px; + -webkit-border-top-left-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-topleft: 6px; + border-top-right-radius: 6px; + border-top-left-radius: 6px; + text-shadow: -1px -1px 0 rgb(93, 69, 35), + 1px -1px 0 rgb(93, 69, 35), + -1px 1px 0 rgb(93, 69, 35), + 1px 1px 0 rgb(93, 69, 35); + padding-left: 5px; +} +.navigation { + display: block; + margin-top: 0; + margin-bottom: 0; + min-height: 20px; +/* border: 1px solid #000; */ +} +.navi-menu { + margin-left: 0; +} +.menu-item { + font-size: 20px; + display: inline; + min-width: 150px; + height: 50px; + margin-left: 0; + margin-right: 10px; + padding: 5px; + border: .5px solit #000; + -webkit-border-top-right-radius: 6px; + -webkit-border-top-left-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-topleft: 6px; + border-top-right-radius: 6px; + border-top-left-radius: 6px; + box-shadow: 5px 5px 5px #eee; +} +.menu-selected { + font-size: 20px; + display: inline; + min-width: 150px; + height: 50px; + margin-left: 0; + margin-right: 10px; + padding: 5px; + border: .5px solit #000; + -webkit-border-top-right-radius: 6px; + -webkit-border-top-left-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-topleft: 6px; + border-top-right-radius: 6px; + border-top-left-radius: 6px; + box-shadow: 5px 5px 5px #eee; + background: rgb(73, 90, 88); + background: -moz-linear-gradient(bottom, rgba(73, 90, 88, 1), rgba(73, 90, 88, 0.5), rgba(73, 90, 88, 0)); + background: -webkit-gradient(linear, bottom, top, from(rgba(73, 90, 88, 1)), color-stop(0.5, rgba(73, 90, 88, 0.5)), to(rgba(73, 90, 88, 0))); + background: linear-gradient(to top, rgba(73, 90, 88, 1), rgba(73, 90, 88, 0.2)); + color: rgb(247, 254, 236); + text-shadow: -1px -1px 0 rgb(93, 69, 35), + 1px -1px 0 rgb(93, 69, 35), + -1px 1px 0 rgb(93, 69, 35), + 1px 1px 0 rgb(93, 69, 35); +} +.menu-item a { + text-decoration: none; +} +#sqlite-admin-wrap { + color: #1d1d1d; + font-size: 10pt; + border: 1px solid #ddd; +/* border-top: 0; */ + -webkit-border-bottom-right-radius: 6px; + -webkit-border-bottom-left-radius: 6px; + -moz-border-radius-bottomright: 6px; + -moz-border-radius-bottomleft: 6px; + border-bottom-right-radius: 6px; + border-bottom-left-radius: 6px; + display: block; + float: left; + min-height: 100px; + position: relative; + width: 47%; + margin-top: 10px; + padding: 5px; + box-shadow: 5px 5px 5px #eee; + z-index: 1; +} +#sqlite-admin-side-wrap { + color: #1d1d1d; + font-size: 10pt; + border: 1px solid #ddd; +/* border-top: 0; */ + -webkit-border-bottom-right-radius: 6px; + -webkit-border-bottom-left-radius: 6px; + -moz-border-radius-bottomright: 6px; + -moz-border-radius-bottomleft: 6px; + border-bottom-right-radius: 6px; + border-bottom-left-radius: 6px; + display: block; + float: left; + min-height: 100px; + position: relative; + width: 47%; + margin-top: 10px; + padding: 5px; + box-shadow: 5px 5px 5px #eee; + z-index: 1; +} +p { + text-indent: 15px; + line-height: 150%; + margin-left: 10px; + margin-right: 10px; +} +ul { + margin-left: 20px; +} +ol { + margin-left: 40px; +} +pre.code { + margin-left: 10px; + background: #eee; +} +.alt { + background: rgb(247, 254, 236); +} +.em { + font-weight: bold; + text-transform: capitalize; +} diff --git a/styles/style.css b/styles/style.css new file mode 100644 index 0000000..a285daa --- /dev/null +++ b/styles/style.css @@ -0,0 +1,216 @@ +@CHARSET "UTF-8"; +#sqlite-admin-wrap h2, +#sqlite-admin-side-wrap h2 { + background: rgb(73, 90, 88); + background: -moz-linear-gradient(bottom, rgba(73, 90, 88, 1), rgba(73, 90, 88, 0.5), rgba(73, 90, 88, 0)); + background: -webkit-gradient(linear, bottom, top, from(rgba(73, 90, 88, 1)), color-stop(0.5, rgba(73, 90, 88, 0.5)), to(rgba(73, 90, 88, 0))); + background: linear-gradient(to top, rgba(73, 90, 88, 1), rgba(73, 90, 88, 0.2)); + color: rgb(247, 254, 236); + -webkit-border-top-right-radius: 6px; + -webkit-border-top-left-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-topleft: 6px; + border-top-right-radius: 6px; + border-top-left-radius: 6px; + text-shadow: -1px -1px 0 rgb(93, 69, 35), + 1px -1px 0 rgb(93, 69, 35), + -1px 1px 0 rgb(93, 69, 35), + 1px 1px 0 rgb(93, 69, 35); + padding-left: 5px; +} +h3 { + clear: both; +} +.navigation { + display: block; + margin-top: 0; + margin-bottom: 0; + min-height: 20px; +/* border: 1px solid #000; */ +} +.navi-menu { + margin-left: 0; +} +.menu-item { + font-size: 20px; + display: inline; + min-width: 150px; + height: 50px; + margin-left: 0; + margin-right: 10px; + padding: 5px; + border: .5px solit #000; + -webkit-border-top-right-radius: 6px; + -webkit-border-top-left-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-topleft: 6px; + border-top-right-radius: 6px; + border-top-left-radius: 6px; + box-shadow: 5px 5px 5px #eee; +} +.menu-selected { + font-size: 20px; + display: inline; + min-width: 150px; + height: 50px; + margin-left: 0; + margin-right: 10px; + padding: 5px; + border: .5px solit #000; + -webkit-border-top-right-radius: 6px; + -webkit-border-top-left-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-topleft: 6px; + border-top-right-radius: 6px; + border-top-left-radius: 6px; + box-shadow: 5px 5px 5px #eee; + background: rgb(73, 90, 88); + background: -moz-linear-gradient(bottom, rgba(73, 90, 88, 1), rgba(73, 90, 88, 0.5), rgba(73, 90, 88, 0)); + background: -webkit-gradient(linear, bottom, top, from(rgba(73, 90, 88, 1)), color-stop(0.5, rgba(73, 90, 88, 0.5)), to(rgba(73, 90, 88, 0))); + background: linear-gradient(to top, rgba(73, 90, 88, 1), rgba(73, 90, 88, 0.2)); + color: rgb(247, 254, 236); + text-shadow: -1px -1px 0 rgb(93, 69, 35), + 1px -1px 0 rgb(93, 69, 35), + -1px 1px 0 rgb(93, 69, 35), + 1px 1px 0 rgb(93, 69, 35); +} +.menu-item a { + text-decoration: none; +} +#sqlite-admin-wrap { + color: #1d1d1d; + font-size: 10pt; + border: 1px solid #ddd; +/* border-top: 0; */ + -webkit-border-bottom-right-radius: 6px; + -webkit-border-bottom-left-radius: 6px; + -moz-border-radius-bottomright: 6px; + -moz-border-radius-bottomleft: 6px; + border-bottom-right-radius: 6px; + border-bottom-left-radius: 6px; + display: block; + float: left; + min-height: 100%; + position: relative; + width: 60%; + margin-top: 10px; + padding: 5px; + box-shadow: 5px 5px 5px #eee; + z-index: 1; +} +#sqlite-admin-side-wrap { + color: #1d1d1d; + font-size: 10pt; + border: 1px solid #ddd; +/* border-top: 0; */ + -webkit-border-bottom-right-radius: 6px; + -webkit-border-bottom-left-radius: 6px; + -moz-border-radius-bottomright: 6px; + -moz-border-radius-bottomleft: 6px; + border-bottom-right-radius: 6px; + border-bottom-left-radius: 6px; + display: block; + float: left; + min-height: 100%; + position: relative; + width: 35%; + margin-top: 10px; + padding: 5px 5px 5px 5px; + box-shadow: 5px 5px 5px #eee; + z-index: 1; +} +p { + text-indent: 15px; + line-height: 150%; +} +table#sys-info{ +/* width: 600px; */ + width: 450px; +} +table#status { + width: 450px; +} +table#sqlite-table { +/* width: 700px; */ + width: 650px; +} +th.tbl-name { + width: 200px; +} +th.tbl_owner { + width: 105px; +} +th.tbl_index { + width: 350px; +} +td.system { + color: rgb(153, 0, 0); +} +td.user { + color: rgb(0, 0, 255); +} +td.menu-title { + width: 90px; +} +table.statement { + width: 500px; +} +ul { + margin-left: 20px; +} +ol { + margin-left: 40px; +} +pre.code { + padding: 5px 5px 5px 5px; + margin-left: 15px; + margin-right: 10px; + background: #eee; +} +tr.incompatible { + background: rgb(251, 229, 221); +} +tr.workaround { + background: rgb(217, 232, 237); +} +tr.compatible { +} +th.active-plugins { + width: 100px; +} +th.compatible { + width: 80px; +} +input.button-primary { + display: block; + clear: both; + width: 100px; +} +.alt { + background: rgb(247, 254, 236); +} +table#patch-files .item { + width: 40px; +} +.alert { + color: rgb(256, 0, 0); +} +div.alert { + display: block; + width: 95%; + text-align: center; + margin: 0 auto; + color: rgb(256, 0, 0); + text-transform: capitalize; +} +blockquote.caution { + display: block; + width: 95%; + border: 3px double rgb(0, 0, 0); + margin: 0 auto; + padding: 5px; +} +blockquote.caution > p { + margin: 5px; + padding: 0; +} \ No newline at end of file diff --git a/utilities/documentation.php b/utilities/documentation.php new file mode 100644 index 0000000..6727432 --- /dev/null +++ b/utilities/documentation.php @@ -0,0 +1,193 @@ +text_domain; + if (is_multisite() && !current_user_can('manage_network_options')) { + die(__('You are not allowed to access this page!', $domain)); + } elseif (!current_user_can('manage_options')) { + die(__('You are not allowed to access this page!', $domain)); + } + if (isset($_GET['page']) && $_GET['page'] == 'doc') :?> +

+
+

+

+ Plugin Page.', $domain);?> +

+

+ +

+ +

+

+ PDO for WordPress, which enabled WordPress to use SQLite for its database. But PDO for WordPress doesn\'t seem to be maintained any more only to be outdated. SQLite Integration makes use of the basic ideas and framework of PDO for WordPress, adds some new features and updates it to be able to work with the newest version of WordPress(3.5.1 and 3.6 beta).', $domain); ?> +

+

+ SQLite Web Page says — SQLite is a "software library that implements selfcontained, serverless, zero-configuration, transactional SQL database engine". It is "a good choice for small to medium size websites". It\'s small and portable, and you don\'t need any database server system.', $domain); ?> +

+

+ +

+

+ +

+
    +
  1. +
  2. +
  3. +
  4. +
  5. +
  6. +
+

+ +

+ +

+

+ +

+
    +
  1. ', $domain);?> +
  2. +
  3. ', $domain);?> + Patch Utility. See also the Plugin Page for more details.', $domain), $utils->show_parent());?>
  4. +
+

+ Support Forum.', $domain);?> +

+

+

+ +

+

+ +

+ +

+

+ +

+ +

+ +

+
+ + +
+

+

+ +

+

+ System Info page. To see more details, please visit the Plugin Page.', $domain), $utils->show_parent());?> +

+ + + + + + + + + + + + + compat, array('No', 'Probably No', 'Needs Patch'))) :?> + + + compat, 'patch') !== false) :?> + + compat, 'probably no')) :?> + + + + + + + + + + +
name;?>reason;?>
+ +

+

+ +

+

+ My recommendation is not to use caching plugins. Even so, if you want a caching plugin, you could try WP Super Cache, which doesn\'t use db.php file. But no warranty, try at your own risk.', $domain);?> +

+

+ +

+

+

+ +

+

+ +

+
+$postRes = mysql_query($sql,$wpdb->dbh);
+
+

+ +

+
+if ( version_compare(mysql_get_server_info(), '4.1.0', '>=') ) {
+
+

+ +

+

+ +

+
+$postRes = $wpdb->query($sql);
+
+
+if ( version_compare($wpdb->db_version(), '4.1.0', '>=') ) {
+
+

+ +

+

+

+ +

+

+ WordPress Related Posts or Related Posts or others. They are working fine with SQLite Integration!', $domain);?> +

+
+ \ No newline at end of file diff --git a/utilities/patch.php b/utilities/patch.php new file mode 100644 index 0000000..236e110 --- /dev/null +++ b/utilities/patch.php @@ -0,0 +1,340 @@ +&1', $out, $val); + } else { + exec('which patch 2>&1', $out, $val); + } + if ($val != 0) { + $patch_results['error'] = __('Patch command is not found', $domain); + return $patch_results; + } elseif (!is_executable(trim($out[0]))) { + $patch_results['error'] = __('Patch command is not executable', $domain); + return $patch_results; + } else { + $patch_command = trim($out[0]) . ' -s -N -p1'; + } + $installed_plugins = get_plugins(); + foreach ($file_names as $file) { + if (preg_match('/_(.*)\.patch/i', $file, $match)) { + $plugin_version = trim($match[1]); + $plugin_basename = preg_replace('/_.*\.patch$/i', '', $file); + foreach (array_keys($installed_plugins) as $key) { + if (stripos($key, $plugin_basename) !== false) { + $installed_plugin_version = $installed_plugins[$key]['Version']; + break; + } + } + } else { + $patch_results['error'] = __('Patch file name is invalid', $domain); + break; + } + if (version_compare($installed_plugin_version, $plugin_version, '!=')) { + $patch_results['error'] = __('Patch file version does not match with that of your plugin.', $domain); + break; + } + $plugin_dir = WP_PLUGIN_DIR.'/'.$plugin_basename; + $patch_file = SQLitePatchDir.'/'.$file; + $command = $patch_command.' <'.$patch_file.' 2>&1'; + if (chdir($plugin_dir)) { + exec("$command", $output, $retval); + } else { + $patch_results[$file] = __('Error! Plugin directory is not accessible.', $domain); + } + if ($retval == 0) { + $patch_results[$file] = __('is patched successfully.', $domain); + } else { + foreach ($output as $val) { + $message .= $val.'
'; + } + $patch_results[$file] = sprintf(__('Error! Messages: %s', $domain), $message); + } + } + return $patch_results; + } + /** + * Delete uploaded patch file(s). + * If patch file(s) is not selected, returns false. + * Or else returns array contains messages. + * @return boolean|array + */ + private function delete_patch_files() { + $file_names = array(); + $rm_results = array(); + if (isset($_POST['plugin_checked'])) { + $file_names = $_POST['plugin_checked']; + } else { + return false; + } + $command = 'rm -f'; + foreach ($file_names as $file) { + if (chdir(SQLitePatchDir)) { + exec("$command $file", $output, $retval); + } else { + $rm_results[$file] = __('Error!: patches directory is not accessible.', $domain); + } + if ($retval > 0) { + $rm_results[$file] = sprintf(__('Error! Messages: %s', $domain), $output); + } else { + $rm_results[$file] = sprintf(__('File %s is deleted.', $domain), $file); + } + } + return $rm_results; + } + /** + * Uploads a patch file. + * No return values. + */ + private function upload_file() { + if (!file_exists(SQLitePatchDir) || !is_dir(SQLitePatchDir)) { + mkdir(SQLitePatchDir, 0705, true); + } + if (is_uploaded_file($_FILES['upfile']['tmp_name'])) { + if (move_uploaded_file($_FILES['upfile']['tmp_name'], SQLitePatchDir.'/'.$_FILES['upfile']['name'])) { + $message = __('File is uploaded', $domain); + echo '
'.$message.'
'; + chmod(SQLitePatchDir.'/'.$_FILES['upfile']['name'], 0644); + } else { + $message = __('File is not uploaded', $domain); + echo '
'.$message.'
'; + } + } else { + $message = __('File is not selected', $domain); + echo '
'.$message.'
'; + } + } + /** + * Displays patch util page + */ + function show_patch_page() { + global $utils; + $domain = $utils->text_domain; + if (is_multisite() && !current_user_can('manage_network_options')) { + die(__('You are not allowed to access this page!', $domain)); + } elseif (!current_user_can('manage_options')) { + die(__('You are not allowed to access this page!', $domain)); + } + if (isset($_POST['apply_patch'])) { + check_admin_referer('sqlitewordpress-plugin-manip-stats'); + if (is_multisite() && !current_user_can('manage_network_options')) { + die(__('You are not allowed to do this operation!', $domain)); + } elseif (!current_user_can('manage_options')) { + die(__('You are not allowed to do this operation!', $domain)); + } + $result = $this->apply_patches(); + if ($result === false) { + $message = __('Please select patch file(s)', $domain); + echo '
'.$message.'
'; + } elseif (is_array($result) && count($result) > 0) { + echo '
'; + foreach ($result as $key => $val) { + echo $key.' => '.$val.'
'; + } + echo '
'; + } else { + $message = __('None of the patches is applied!'); + echo '
'.$message.'
'; + } + } + if (isset($_POST['patch_file_delete'])) { + check_admin_referer('sqlitewordpress-plugin-manip-stats'); + if (is_multisite() && !current_user_can('manage_network_options')) { + die(__('You are not allowed to do this operation!', $domain)); + } elseif (!current_user_can('manage_options')) { + die(__('You are not allowed to do this operation!', $domain)); + } + $result = $this->delete_patch_files(); + if ($result === false) { + $message = __('Please select patch file(s)', $domain); + echo '
'.$message.'
'; + } elseif (is_array($result) && count($result) > 0) { + echo '
'; + foreach ($result as $key => $val) { + echo $key.' => '.$val.'
'; + } + echo '
'; + } else { + $message = __('Error! Please remove files manually'); + echo '
'.$message.'
'; + } + } + if (isset($_POST['upload'])) { + check_admin_referer('sqlitewordpress-plugin-patch-file-stats'); + if (is_multisite() && !current_user_can('manage_network_options')) { + die(__('You are not allowed to do this operation!', $domain)); + } elseif (!current_user_can('manage_options')) { + die(__('You are not allowed to do this operation!', $domain)); + } + $result = $this->upload_file(); + } + if (isset($_GET['page']) && $_GET['page'] == 'patch') : ?> + +
+

+

+

+ Plugin Page about how to apply a patch file to the plugin. But the command line interface sometimes embarrasses some people, especially newbies.', $domain);?> +

+

+ +

+
    +
  1. Plugin Directory for the substitutes?', $domain)?>
  2. +
  3. +
  4. +
  5. +
+

+ +

+

+ +

+
    +
  1. +
  2. +
  3. +
  4. +
+

+ +

+ +

+
    +
  1. +
  2. +
  3. +
+

+

+ +

+
    +
  1. +
  2. +
  3. +
  4. +
+

+

+ + + + + + + + + + + +
+
+ +
+ + +
+
+
+ + + + + + + + + + + get_patch_files(); + if (!empty($files)) : ?> + + + + + + + + +
+

+ + +

+
+
+
+ +
+
+ +
+
+

+ +

+
+
+ \ No newline at end of file diff --git a/utilities/plugin_lists.json b/utilities/plugin_lists.json new file mode 100644 index 0000000..5055e89 --- /dev/null +++ b/utilities/plugin_lists.json @@ -0,0 +1,313 @@ +[ + { + "name":"Akismet", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"All In One SEO Pack", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Any Mobile Theme Switcher", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"BAW Manual Related Posts", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Better Related Posts", + "compat":"No", + "reason":"FULLTEXT index", + "class":"incompatible" + }, + + { + "name":"Breadcrumb NavXT", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Broken Link Checker", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Browser Shots", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Camera slideshow", + "compat":"Needs Patch", + "patch_url":"http://dogwood.skr.jp/wordpress/plugins/", + "reason":"MySQL function", + "class":"workaround" + }, + + { + "name":"Category Order and Taxonomy Terms Order", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Contact Form 7", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Contact Form 7 reCAPTCHA extension", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Crayon Syntax Highlighter", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"DB Cache Reloaded Fix", + "compat":"Probably No", + "reason":"db.php conflict", + "class":"probable" + }, + + { + "name":"Debug Bar", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Debug Bar Console", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Debug Bar Extender", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Dynamic To Top", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Google Analyticator", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Google Analytics Popular Posts", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Google XML Sitemaps", + "compat":"Needs Patch", + "patch_url":"http://dogwood.skr.jp/wordpress/plugins/", + "reason":"MySQL function", + "class":"workaround" + }, + + { + "name":"Hello Dolly", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"HyperDB", + "compat":"Probably No", + "reason":"db.php conflict", + "class":"probable" + }, + + { + "name":"Jetpack by WordPress.com", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Ktai Style", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Limit Login Attempts", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Optimize Database after Deleting Revisions", + "compat":"Probably No", + "reason":"MySQL function/MySQL specific table", + "class":"workaround" + }, + + { + "name":"Polylang", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Related Posts", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Revision Cleaner", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Search Everything", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Search Meter", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"SQLite Integration", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Synchi", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Theme-Check", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Wordfence Security", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"WordPress Beta Tester", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"WordPress Importer", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Wordpress Popular Posts", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"WordPress Related Posts", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"WP Multibyte Patch", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"WP-PageNavi", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"WP-PostRatings", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"WP-reCAPTCHA", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"WP Social Bookmarking Light", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"WP Super Cache", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"WP Video Lightbox", + "compat":"Checked", + "class":"compatible" + }, + + { + "name":"Wysija Newsletters", + "compat":"Needs Patch", + "patch_url":"http://dogwood.skr.jp/wordpress/plugins/", + "reason":"MySQL function/table name", + "class":"workaround" + }, + + { + "name":"W3 Total Cache", + "compat":"Probably No", + "reason":"db.php conflict", + "class":"probable" + }, + + { + "name":"Yet Another Related Posts Plugin", + "compat":"No", + "reason":"FULLTEX index", + "class":"incompatible" + } +] \ No newline at end of file diff --git a/utilities/utility.php b/utilities/utility.php new file mode 100644 index 0000000..a122b2d --- /dev/null +++ b/utilities/utility.php @@ -0,0 +1,679 @@ + WordPress Version + * sys_info['PHP'] => PHP Version + * @return array + */ + private function get_system_info() { + global $wp_version; + $sys_info = array(); + $sys_info['WordPress'] = $wp_version; + $sys_info['PHP'] = PHP_VERSION; + return $sys_info; + } + /** + * function to return various database information + * @return assoc array + */ + private function get_database_status() { + global $wpdb; + $status = array(); + $db_size = $this->get_database_size(); + $encoding = $wpdb->get_var("PRAGMA encoding"); + $integrity = $wpdb->get_var("PRAGMA integrity_check"); + $page_size = $wpdb->get_var("PRAGMA page_size"); + $page_count = $wpdb->get_var("PRAGMA page_count"); + $unused_page = $wpdb->get_var("PRAGMA freelist_count"); + $collation_list = $wpdb->get_results("PRAGMA collation_list"); + $compile_options = $wpdb->get_results("PRAGMA compile_options"); + foreach ($collation_list as $col) { + $collations[] = $col->name; + } + foreach ($compile_options as $opt) { + $options[] = $opt->compile_option; + } + $status['size'] = $db_size; + $status['integrity'] = $integrity; + $status['pagesize'] = $page_size; + $status['page'] = $page_count; + $status['unused'] = $unused_page; + $status['encoding'] = $encoding; + $status['collations'] = $collations; + $status['options'] = $options; + return $status; + } + /** + * function to return associative array + * array( table name => array( index name ( column name ))) + * for each table in the database + * @return array + */ + private function get_tables_info() { + global $wpdb; + $table_info = array(); + $tables = $wpdb->get_col("SHOW TABLES"); + foreach ($tables as $table) { + $index_object = $wpdb->get_results("SHOW INDEX FROM $table"); + if (empty($index_object)) { + $table_info[$table][] = 'no index'; + } else { + foreach ($index_object as $index) { + $table_info[$table][] = $index->Key_name . ' ( ' . $index->Column_name . ' )'; + } + } + } + $table_info = array_reverse($table_info); + return $table_info; + } + /** + * function to return the autoincremented values of each table + * @return assoc array name => sequence, or false + */ + private function get_sequence() { + global $wpdb; + $sequence_info = array(); + $results = $wpdb->get_results("SELECT name, seq FROM sqlite_sequence"); + if (is_null($results) || empty($results)) { + return false; + } else { + foreach ($results as $result) { + $sequence_info[$result->name] = $result->seq; + } + return $sequence_info; + } + } + /** + * function to return contents of 'wp-content/db.php' file + * if the file is not existent, returns false. + * @return string|boolean + */ + private function show_db_php() { + if (defined('WP_CONTENT_DIR')) { + $file = WP_CONTENT_DIR . '/db.php'; + } else { + $file = ABSPATH . 'wp-content/db.php'; + } + if (file_exists($file)) { + if (is_readable($file)) { + $contents = file_get_contents($file); + echo $contents; + } else { + echo 'file is not readable'; + } + } else { + echo 'file doesn\'t exist'; + return false; + } + } + /** + * function to get the textarea contents and write into db.php file + * @param string $contents + * @return boolean + */ + private function save_db_php($contents) { + if (defined('WP_CONTENT_DIR')) { + $file = WP_CONTENT_DIR . '/db.php'; + } else { + $file = ABSPATH . 'wp-content/db.php'; + } + $fh = fopen($file, "w+"); + if ($fh) { + if (flock($fh, LOCK_EX)) { + if (fwrite($fh, $contents) === false) { + return false; + } + flock($fh, LOCK_UN); + } else { + return false; + } + } + fclose($fh); + return true; + } + /** + * function to optimize database file + * only to give vacuum command to SQLite + * @return boolean + */ + private function optimize_db() { + global $wpdb; + $result = $wpdb->query("OPTIMIZE"); + return $result; + } + /** + * function to get SQLite database file size + * @return string + */ + private function get_database_size() { + $db_file = FQDB; + if (file_exists($db_file)) { + $size = filesize($db_file); + clearstatcache(false, $db_file); + return $this->convert_to_formatted_number($size); + } + } + /** + * function to format file size to unit byte + * @param integer $size + * @return string + */ + private function convert_to_formatted_number($size) { + $unim = array('Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'); + $count = 0; + while ($size >= 1024) { + $count++; + $size = $size / 1024; + } + return number_format($size, ($count ? 2 : 0), '.', ',') . ' ' . $unim[$count]; + } + + /** + * function to echo plugins info table component + */ + private function show_plugins_info() { + $domain = $this->text_domain; + if (file_exists(SQLiteListFile)) { + $contents = file_get_contents(SQLiteListFile); + $plugin_info_list = json_decode($contents); + $plugins = get_plugins(); + foreach ($plugins as $key => $data) { + $name = ''.$data['Name'].''; + foreach ($plugin_info_list as $plugin_info) { + if ($data['Name'] == $plugin_info->name) { + $class = 'class="'.$plugin_info->class.'"'; + // for Internationalization... it's a redundant codes, mm... + // I might have made a mistake to store data in json format... + switch ($plugin_info->compat) { + case 'Needs Patch': + if (!empty($plugin_info->patch_url)) { + $compat = ''.__('Needs Patch', $domain).''; + } else { + $compat = __('Needs Patch', $domain); + } + break; + case 'Probably No': + $compat = __('Probably No', $domain); + break; + case 'Probably Yes': + $compat = __('Probably Yes', $domain); + break; + case 'No': + $compat = __('No', $domain); + break; + case 'Checked': + $compat = __('Checked', $domain); + break; + default: + $compat = __('Not Checked', $domain); + break; + } + break; + } else { + $class = 'class="compatible"'; + $compat = __('Not Checked', $domain); + } + } + if (is_plugin_active_for_network($key)) { + echo '"; + echo sprintf('%1$s%2$s%3$s', $name, __('Sitewide Active', $domain), $compat); + } elseif (is_plugin_active($key)) { + echo '"; + echo sprintf('%1$s%2$s%3$s', $name, __('Active', $domain), $compat); + } else { + echo '"; + echo sprintf('%1$s%2$s%3$s', $name, __('Inactive', $domain), $compat); + } + echo ''; + } + } + } + + /** + * function to return output of phpinfo() as an array + * See PHP Manual + * @return array + */ + private function parse_php_modules() { + ob_start(); + phpinfo(INFO_MODULES); + $infos = ob_get_contents(); + ob_end_clean(); + + $infos = strip_tags($infos, '

'); + $infos = preg_replace('/]*>([^<]+)<\/th>/', "\\1", $infos); + $infos = preg_replace('/]*>([^<]+)<\/td>/', "\\1", $infos); + $info_array = preg_split('/(

[^<]+?<\/h2>)/', $infos, -1, PREG_SPLIT_DELIM_CAPTURE); + $modules = array(); + for ($i = 1; $i < count($info_array); $i++) { + if (preg_match('/

([^<]+)<\/h2>/', $info_array[$i], $match)) { + $name = trim($match[1]); + $info_array2 = explode("\n", $info_array[$i+1]); + foreach ($info_array2 as $info) { + $pattern = '([^<]+)<\/info>'; + $pattern3 = "/$pattern\\s*$pattern\\s*$pattern/"; + $pattern2 = "/$pattern\\s*$pattern/"; + if (preg_match($pattern3, $info, $match)) { + $modules[$name][trim($match[1])] = array(trim($match[2]), trim($match[3])); + } elseif (preg_match($pattern2, $info, $match)) { + $modules[$name][trim($match[1])] = trim($match[2]); + } + } + } + } + return $modules; + } + /** + * function to echo PHP module info + * @param string $module_name + * @param string $setting_name + */ + private function get_module_setting($module_name, $setting_name) { + $module_info = $this->parse_php_modules(); + echo $module_info[$module_name][$setting_name]; + } + function show_parent() { + if (function_exists('is_multisite') && is_multisite()) { + return 'settings.php'; + } else { + return 'options-general.php'; + } + } + + function welcome() { + $domain = $this->text_domain; + if (isset($_GET['page']) && $_GET['page'] == 'sqlite-integration') :?> +
+

+

+ +

+

+ +

+

+ +

+

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + text_domain; + if (is_multisite() && !current_user_can('manage_network_options')) { + die(__('You are not allowed to access this page!', $domain)); + } elseif (!current_user_can('manage_options')) { + die(__('You are not allowed to access this page!', $domain)); + } + if (isset($_GET['page']) && $_GET['page'] == 'sys-info') :?> + +
+

+

+ get_system_info(); ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
get_module_setting('PDO', 'PDO support');?>
get_module_setting('PDO', 'PDO drivers');?>
get_module_setting('pdo_sqlite', 'PDO Driver for SQLite 3.x');?>
get_module_setting('pdo_sqlite', 'SQLite Library');?> +
+ +

+ + + + + + + + + get_database_status();?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + '; + echo ($i+1).'. '.$col; + $i++; + } + ?> +
+ '; + echo ($i+1).'. '.$op; + $i++; + } + ?> +
+ +

+

+ +

+ + + + + + + + + get_tables_info(); + $table_seq = $this->get_sequence(); + $network_tables = array(); + if (is_multisite()) { + $tmp_tables = $wpdb->tables('blog', false); + $blogs = $wpdb->get_col("SELECT * FROM {$wpdb->prefix}blogs"); + if (count($blogs) > 1) { + foreach ($blogs as $id) { + if ($id == 1) continue; + foreach ($tmp_tables as $tmp_tbl) { + $network_tables[] = $wpdb->prefix.$id.'_'.$tmp_tbl; + } + } + } + } + foreach ($table_info as $tbl_name => $index) : ?> + tables('all', true)) || in_array($tbl_name, $network_tables) || $tbl_name == 'sqlite_sequence') { + $which_table = 'system'; + } else { + $which_table = 'user'; + } + echo ''; + if (array_key_exists($tbl_name, $table_seq)) $tbl_name .= " ($table_seq[$tbl_name])"; + echo ''; + echo '';?> + + + + +
+
' . $tbl_name . '' . $which_table . ' table';} ?>
+
+ +
+

+

+ +

+ + + + + + + + + + show_plugins_info();?> + +
+
+ text_domain; + if (is_multisite() && !current_user_can('manage_network_options')) { + die(__('You are not allowed to access this page!', $domain)); + } elseif (!current_user_can('manage_options')) { + die(__('You are not allowed to access this page!', $domain)); + } + if (isset($_POST['sqlitewordpress_log_reset'])) { + check_admin_referer('sqlitewordpress-log-reset-stats'); + if ($this->clear_log_file()) { + $messages = __('Log cleared', $domain); + echo '
'.$messages.'
'; + } else { + $messages = __('Log not cleared', $domain); + echo '
'.$messages.'
'; + } + } + if (isset($_POST['sqlitewordpress_db_save'])) { + check_admin_referer('sqlitewordpress-db-save-stats'); + if (isset($_POST['dbfile'])) { + $contents = $_POST['dbfile']; + if (get_magic_quotes_gpc() || version_compare(PHP_VERSION, '5.4', '>=')) { + $contents = stripslashes($contents); + } + if ($this->save_db_php($contents)) { + $messages = __('db.php was saved', $domain); + echo '
'.$messages.'
'; + } else { + $messages = __('Error! db.php couldn\'t be saved', $domain); + echo '
'.$messages.'
'; + } + } + } + if (isset($_POST['sqlitewordpress_db_optimize'])) { + check_admin_referer('sqlitewordpress-db-optimize-stats'); + $size_before = $this->get_database_size(); + $result = $this->optimize_db(); + if ($result) { + $size_after = $this->get_database_size(); + $messages = sprintf(__('Optimization finished. Before optimization: %1$s, After optimization: %2$s.', $domain), $size_before, $size_after); + echo '
'.$messages.'
'; + } else { + $messages = __('Optimization failed', $domain); + echo '
'.$messages.'
'; + } + } + if (isset($_GET['page']) && $_GET['page'] == 'setting-file') :?> + +
+

+

+

+ +

+
+ +

+ +

+
+

+

+ +

+
+ + +

+ +

+
+ +

+

+ If you don\'t understand well, please don\'t edit this file.', $domain)?> +

+
+ + +

+ +

+
+ +
+ \ No newline at end of file