diff --git a/admin/manage-comments.php b/admin/manage-comments.php index d5838904..0c805e1a 100644 --- a/admin/manage-comments.php +++ b/admin/manage-comments.php @@ -243,7 +243,7 @@ $(document).ready(function () { } else { var form = $('<form method="post" action="' + t.attr('rel') + '" class="comment-reply">' - + '<p><label for="text" class="visuallyhidden"><?php _e('内容'); ?></label><textarea id="text" name="text" class="w-90" rows="3"></textarea></p>' + + '<p><label for="text" class="visuallyhidden"><?php _e('内容'); ?></label><textarea id="text" name="text" class="w-90 mono" rows="3"></textarea></p>' + '<p><button type="submit" class="btn-s primary"><?php _e('回复'); ?></button> <button type="button" class="btn-s cancel"><?php _e('取消'); ?></button></p>' + '</form>').insertBefore($('.comment-action', td)); @@ -286,7 +286,7 @@ $(document).ready(function () { + '<input class="text-s w-100" type="text" name="url" id="' + id + '-url"></p></form></td>' + '<td valign="top"><form method="post" action="' + t.attr('rel') + '" class="comment-edit-content"><p><label for="' + id + '-text"><?php _e('内容'); ?></label>' - + '<textarea name="text" id="' + id + '-text" rows="6" class="w-90"></textarea></p>' + + '<textarea name="text" id="' + id + '-text" rows="6" class="w-90 mono"></textarea></p>' + '<p><button type="submit" class="btn-s primary"><?php _e('提交'); ?></button> ' + '<button type="button" class="btn-s cancel"><?php _e('取消'); ?></button></p></form></td></tr>') .data('id', id).data('comment', comment).insertAfter(tr); diff --git a/install.php b/install.php index 7dacea6c..ed10b5a2 100644 --- a/install.php +++ b/install.php @@ -303,6 +303,7 @@ list($prefixVersion, $suffixVersion) = explode('/', $currentVersion); $installDb->query($installDb->insert('table.options')->rows(array('name' => 'commentsPostTimeout', 'user' => 0, 'value' => 24 * 3600 * 30))); $installDb->query($installDb->insert('table.options')->rows(array('name' => 'commentsUrlNofollow', 'user' => 0, 'value' => 1))); $installDb->query($installDb->insert('table.options')->rows(array('name' => 'commentsShowUrl', 'user' => 0, 'value' => 1))); + $installDb->query($installDb->insert('table.options')->rows(array('name' => 'commentsMarkdown', 'user' => 0, 'value' => 0))); $installDb->query($installDb->insert('table.options')->rows(array('name' => 'commentsPageBreak', 'user' => 0, 'value' => 0))); $installDb->query($installDb->insert('table.options')->rows(array('name' => 'commentsThreaded', 'user' => 0, 'value' => 1))); $installDb->query($installDb->insert('table.options')->rows(array('name' => 'commentsPageSize', 'user' => 0, 'value' => 20))); diff --git a/install/Mysql.sql b/install/Mysql.sql index 0f6ce0eb..c2498730 100644 --- a/install/Mysql.sql +++ b/install/Mysql.sql @@ -68,6 +68,24 @@ CREATE TABLE `typecho_contents` ( -- -------------------------------------------------------- +-- +-- 表的结构 `typecho_fields` +-- + +CREATE TABLE `typecho_fields` ( + `cid` int(10) unsigned NOT NULL, + `name` varchar(200) NOT NULL, + `type` varchar(8) default 'str', + `str_value` text, + `int_value` int(10) default '0', + `float_value` float default '0', + PRIMARY KEY (`cid`,`name`), + KEY `int_value` (`int_value`), + KEY `float_value` (`float_value`) +) ENGINE=MyISAM DEFAULT CHARSET=%charset%; + +-- -------------------------------------------------------- + -- -- 表的结构 `typecho_metas` -- diff --git a/install/Pgsql.sql b/install/Pgsql.sql index fbede038..7381840f 100644 --- a/install/Pgsql.sql +++ b/install/Pgsql.sql @@ -1,5 +1,5 @@ -- --- Table structure for table `typecho_comments` +-- Table structure for table "typecho_comments" -- CREATE SEQUENCE "typecho_comments_seq"; @@ -25,7 +25,7 @@ CREATE INDEX "typecho_comments_created" ON "typecho_comments" ("created"); -- --- Table structure for table `typecho_contents` +-- Table structure for table "typecho_contents" -- CREATE SEQUENCE "typecho_contents_seq"; @@ -53,9 +53,24 @@ CREATE TABLE "typecho_contents" ( "cid" INT NOT NULL DEFAULT nextval('typecho_c CREATE INDEX "typecho_contents_created" ON "typecho_contents" ("created"); +-- +-- Table structure for table "typecho_fields" +-- + +CREATE TABLE "typecho_fields" ("cid" INT NOT NULL, + "name" VARCHAR(200) NOT NULL, + "type" VARCHAR(8) NULL DEFAULT 'str', + "str_value" TEXT NULL DEFAULT NULL, + "int_value" INT NULL DEFAULT '0', + "float_value" REAL NULL DEFAULT '0', + PRIMARY KEY ("cid","name") +); + +CREATE INDEX "typecho_fields_int_value" ON "typecho_fields" ("int_value"); +CREATE INDEX "typecho_fields_float_value" ON "typecho_fields" ("float_value"); -- --- Table structure for table `typecho_metas` +-- Table structure for table "typecho_metas" -- CREATE SEQUENCE "typecho_metas_seq"; @@ -74,7 +89,7 @@ CREATE INDEX "typecho_metas_slug" ON "typecho_metas" ("slug"); -- --- Table structure for table `typecho_options` +-- Table structure for table "typecho_options" -- CREATE TABLE "typecho_options" ( "name" VARCHAR(32) NOT NULL DEFAULT '', @@ -84,7 +99,7 @@ CREATE TABLE "typecho_options" ( "name" VARCHAR(32) NOT NULL DEFAULT '', ); -- --- Table structure for table `typecho_relationships` +-- Table structure for table "typecho_relationships" -- CREATE TABLE "typecho_relationships" ( "cid" INT NOT NULL DEFAULT '0', @@ -93,7 +108,7 @@ CREATE TABLE "typecho_relationships" ( "cid" INT NOT NULL DEFAULT '0', ); -- --- Table structure for table `typecho_users` +-- Table structure for table "typecho_users" -- CREATE SEQUENCE "typecho_users_seq"; diff --git a/install/SQLite.sql b/install/SQLite.sql index 73b05b8f..fb720d52 100644 --- a/install/SQLite.sql +++ b/install/SQLite.sql @@ -37,6 +37,18 @@ CREATE TABLE typecho_contents ( "cid" INTEGER NOT NULL PRIMARY KEY, CREATE UNIQUE INDEX typecho_contents_slug ON typecho_contents ("slug"); CREATE INDEX typecho_contents_created ON typecho_contents ("created"); +CREATE TABLE "typecho_fields" ("cid" INTEGER NOT NULL, + "name" varchar(200) NOT NULL, + "type" varchar(8) default 'str', + "str_value" text, + "int_value" int(10) default '0', + "float_value" real default '0' +); + +CREATE UNIQUE INDEX typecho_fields_cid_name ON typecho_fields ("cid", "name"); +CREATE INDEX typecho_fields_int_value ON typecho_fields ("int_value"); +CREATE INDEX typecho_fields_float_value ON typecho_fields ("float_value"); + CREATE TABLE typecho_metas ( "mid" INTEGER NOT NULL PRIMARY KEY, "name" varchar(200) default NULL , "slug" varchar(200) default NULL , diff --git a/var/Typecho/Common.php b/var/Typecho/Common.php index 9179c35a..c8730bb7 100644 --- a/var/Typecho/Common.php +++ b/var/Typecho/Common.php @@ -20,7 +20,7 @@ class Typecho_Common { /** 程序版本 */ - const VERSION = '0.9/13.11.17'; + const VERSION = '0.9/13.11.24'; /** * 缓存的包含路径 @@ -634,7 +634,8 @@ EOF; public static function stripTags($html, $allowableTags = NULL) { if (!empty($allowableTags) && preg_match_all("/\<([a-z]+)([^>]*)\>/is", $allowableTags, $tags)) { - self::$_allowableTags = '|' . implode('|', $tags[1]) . '|'; + self::$_allowableTags = '|' . implode('|', + array_unique(array_map('trim', array_map('strtolower', $tags[1])))) . '|'; if (in_array('code', $tags[1])) { $html = self::lockHTML($html); diff --git a/var/Typecho/Db.php b/var/Typecho/Db.php index c718006e..61c2286f 100644 --- a/var/Typecho/Db.php +++ b/var/Typecho/Db.php @@ -163,6 +163,17 @@ class Typecho_Db return $this->_prefix; } + /** + * getConfig + * + * @access public + * @return void + */ + public function getConfig() + { + return $this->_config; + } + /** * 获取SQL词法构建器实例化对象 * diff --git a/var/Upgrade.php b/var/Upgrade.php index 775b6a55..631ccd1f 100644 --- a/var/Upgrade.php +++ b/var/Upgrade.php @@ -1004,5 +1004,71 @@ Typecho_Date::setTimezoneOffset($options->timezone); $db->query($db->insert('table.options') ->rows(array('name' => 'frontArchive', 'user' => 0, 'value' => 0))); } + + /** + * v0_9r13_11_24 + * + * @param mixed $db + * @param mixed $options + * @static + * @access public + * @return void + */ + public static function v0_9r13_11_24($db, $options) + { + /* 增加数据表 */ + $adapterName = $db->getAdapterName(); + $prefix = $db->getPrefix(); + + switch (true) { + case false !== strpos($adapterName, 'Mysql'): + $config = $db->getConfig(); + $db->query("CREATE TABLE `{$prefix}fields` ( + `cid` int(10) unsigned NOT NULL, + `name` varchar(200) NOT NULL, + `type` varchar(8) default 'str', + `str_value` text, + `int_value` int(10) default '0', + `float_value` float default '0', + PRIMARY KEY (`cid`,`name`), + KEY `int_value` (`int_value`), + KEY `float_value` (`float_value`) +) ENGINE=MyISAM DEFAULT CHARSET=" . $config[0]->charset, Typecho_Db::WRITE); + break; + + case false !== strpos($adapterName, 'Pgsql'): + $db->query('CREATE TABLE "' . $prefix . 'fields" ("cid" INT NOT NULL, + "name" VARCHAR(200) NOT NULL, + "type" VARCHAR(8) NULL DEFAULT \'str\', + "str_value" TEXT NULL DEFAULT NULL, + "int_value" INT NULL DEFAULT \'0\', + "float_value" REAL NULL DEFAULT \'0\', + PRIMARY KEY ("cid","name") +)', Typecho_Db::WRITE); + $db->query('CREATE INDEX "' . $prefix . 'fields_int_value" ON "' . $prefix . 'fields" ("int_value")', Typecho_Db::WRITE); + $db->query('CREATE INDEX "' . $prefix . 'fields_float_value" ON "' . $prefix . 'fields" ("float_value")', Typecho_Db::WRITE); + break; + + case false !== strpos($adapterName, 'SQLite'): + $db->query('CREATE TABLE "' . $prefix . 'fields" ("cid" INTEGER NOT NULL, + "name" varchar(200) NOT NULL, + "type" varchar(8) default \'str\', + "str_value" text, + "int_value" int(10) default \'0\', + "float_value" real default \'0\' +)', Typecho_Db::WRITE); + $db->query('CREATE UNIQUE INDEX ' . $prefix . 'fields_cid_name ON ' . $prefix . 'fields ("cid", "name")', Typecho_Db::WRITE); + $db->query('CREATE INDEX ' . $prefix . 'fields_int_value ON ' . $prefix . 'fields ("int_value")', Typecho_Db::WRITE); + $db->query('CREATE INDEX ' . $prefix . 'fields_float_value ON ' . $prefix . 'fields ("float_value")', Typecho_Db::WRITE); + + break; + + default: + break; + } + + $db->query($db->insert('table.options') + ->rows(array('name' => 'commentsMarkdown', 'user' => 0, 'value' => 0))); + } } diff --git a/var/Widget/Abstract/Comments.php b/var/Widget/Abstract/Comments.php index dd237aff..7c844d20 100644 --- a/var/Widget/Abstract/Comments.php +++ b/var/Widget/Abstract/Comments.php @@ -111,7 +111,13 @@ class Widget_Abstract_Comments extends Widget_Abstract $text = $this->pluginHandle(__CLASS__)->trigger($plugged)->content($text, $this); if (!$plugged) { - $text = Typecho_Common::cutParagraph($text); + if ($this->options->commentsMarkdown) { + $text = MarkdownExtraExtended::defaultTransform($text); + $text = Typecho_Common::stripTags($text, '<p><br>' . $this->options->commentsHTMLTagAllowed); + } else { + $text = Typecho_Common::stripTags($text, $this->options->commentsHTMLTagAllowed); + $text = Typecho_Common::cutParagraph($text); + } } return $this->pluginHandle(__CLASS__)->contentEx($text, $this); diff --git a/var/Widget/Abstract/Users.php b/var/Widget/Abstract/Users.php index 6ede7bef..65620ecf 100644 --- a/var/Widget/Abstract/Users.php +++ b/var/Widget/Abstract/Users.php @@ -19,6 +19,24 @@ */ class Widget_Abstract_Users extends Widget_Abstract { + /** + * __options + * + * @access protected + * @return Config + */ + protected function __options() + { + $rows = $this->db->fetchAll($this->db->select() + ->from('table.options')->where('user = ?', $this->uid)); + $options = array(); + foreach ($rows as $row) { + $options[$row['name']] = $row['value']; + } + + return new Typecho_Config($options); + } + /** * 判断用户名称是否存在 * diff --git a/var/Widget/Feedback.php b/var/Widget/Feedback.php index 166d13d3..fb4cf7c8 100644 --- a/var/Widget/Feedback.php +++ b/var/Widget/Feedback.php @@ -77,7 +77,7 @@ class Widget_Feedback extends Widget_Abstract_Comments implements Widget_Interfa $validator->addRule('text', 'required', _t('必须填写评论内容')); - $comment['text'] = $this->request->filter(array($this, 'filterText'))->text; + $comment['text'] = $this->request->text; /** 对一般匿名访问者,将用户数据保存一个月 */ if (!$this->user->hasLogin()) { @@ -174,7 +174,7 @@ class Widget_Feedback extends Widget_Abstract_Comments implements Widget_Interfa $trackback['author'] = $this->request->filter('trim')->blog_name; $trackback['url'] = $this->request->filter('trim')->url; - $trackback['text'] = $this->request->filter(array($this, 'filterText'))->excerpt; + $trackback['text'] = $this->request->excerpt; //检验格式 $validator = new Typecho_Validate(); diff --git a/var/Widget/Options/Discussion.php b/var/Widget/Options/Discussion.php index 520e90de..25e48d9c 100644 --- a/var/Widget/Options/Discussion.php +++ b/var/Widget/Options/Discussion.php @@ -47,6 +47,7 @@ class Widget_Options_Discussion extends Widget_Abstract_Options implements Widge $commentsShowOptions = array( 'commentsShowCommentOnly' => _t('仅显示评论, 不显示 Pingback 和 Trackback'), + 'commentsMarkdown' => _t('在评论中使用Markdown语法'), 'commentsShowUrl' => _t('评论者名称显示时自动加上其个人主页链接'), 'commentsUrlNofollow' => _t('对评论者个人主页链接使用 <a href="http://en.wikipedia.org/wiki/Nofollow">nofollow 属性</a>'), 'commentsAvatar' => _t('启用 <a href="http://gravatar.com">Gravatar</a> 头像服务, 最高显示评级为 %s 的头像', @@ -76,6 +77,10 @@ class Widget_Options_Discussion extends Widget_Abstract_Options implements Widge $commentsShowOptionsValue[] = 'commentsShowCommentOnly'; } + if ($this->options->commentsMarkdown) { + $commentsShowOptionsValue[] = 'commentsMarkdown'; + } + if ($this->options->commentsShowUrl) { $commentsShowOptionsValue[] = 'commentsShowUrl'; } @@ -182,6 +187,7 @@ class Widget_Options_Discussion extends Widget_Abstract_Options implements Widge 'commentsPostTimeout', 'commentsPostInterval', 'commentsRequireModeration', 'commentsRequireURL', 'commentsHTMLTagAllowed', 'commentsStopWords', 'commentsIpBlackList'); $settings['commentsShowCommentOnly'] = $this->isEnableByCheckbox($settings['commentsShow'], 'commentsShowCommentOnly'); + $settings['commentsMarkdown'] = $this->isEnableByCheckbox($settings['commentsShow'], 'commentsMarkdown'); $settings['commentsShowUrl'] = $this->isEnableByCheckbox($settings['commentsShow'], 'commentsShowUrl'); $settings['commentsUrlNofollow'] = $this->isEnableByCheckbox($settings['commentsShow'], 'commentsUrlNofollow'); $settings['commentsAvatar'] = $this->isEnableByCheckbox($settings['commentsShow'], 'commentsAvatar');