本文整理汇总了PHP中Attachments类的典型用法代码示例。如果您正苦于以下问题:PHP Attachments类的具体用法?PHP Attachments怎么用?PHP Attachments使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了Attachments类的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的PHP代码示例。
示例1: deleteAttachment
public function deleteAttachment(Attachments $attachment)
{
/** @var myModel $this */
$attachment->delete();
$this->decreaseCount('attachmentCount');
return $this;
}
开发者ID:huoybb,项目名称:standard,代码行数:7,代码来源:attachableTrait.php
示例2: getAttachment
private function getAttachment()
{
// FIXME: Do we really need to mess with memory limits here? We're only reading ~80KB at a time...
@ini_set('memory_limit', '128M');
if (!$this->isRequiredIDValid('id', $_GET)) {
CommonErrors::fatal(COMMONERROR_BADINDEX, $this, 'No attachment ID specified.');
}
$attachmentID = $_GET['id'];
$attachments = new Attachments(-1);
$rs = $attachments->get($attachmentID, false);
if (empty($rs) || md5($rs['directoryName']) != $_GET['directoryNameHash']) {
CommonErrors::fatal(COMMONERROR_BADFIELDS, $this, 'Invalid id / directory / filename, or you do not have permission to access this attachment.');
}
$directoryName = $rs['directoryName'];
$fileName = $rs['storedFilename'];
$filePath = sprintf('attachments/%s/%s', $directoryName, $fileName);
/* Check for the existence of the backup. If it is gone, send the user to a page informing them to press back and generate the backup again. */
if ($rs['contentType'] == 'catsbackup' && !file_exists($filePath)) {
CommonErrors::fatal(COMMONERROR_FILENOTFOUND, $this, 'The specified backup file no longer exists. Please go back and regenerate the backup before downloading. We are sorry for the inconvenience.');
}
// FIXME: Stream file rather than redirect? (depends on download preparer working).
if (!eval(Hooks::get('ATTACHMENT_RETRIEVAL'))) {
return;
}
/* Determine MIME content type of the file. */
$contentType = Attachments::fileMimeType($fileName);
/* Open the file and verify that it is readable. */
$fp = @fopen($filePath, 'r');
if ($fp === false) {
CommonErrors::fatal(COMMONERROR_BADFIELDS, $this, 'This attachment is momentarily offline, please try again later. The support staff has been notified.');
}
/* Set headers for sending the file. */
header('Content-Disposition: inline; filename="' . $fileName . '"');
//Disposition attachment was default, but forces download.
header('Content-Type: ' . $contentType);
header('Content-Length: ' . filesize($filePath));
header('Pragma: no-cache');
header('Expires: 0');
/* Read the file in ATTACHMENT_BLOCK_SIZE-sized chunks from disk and
* output to the browser.
*/
while (!feof($fp)) {
print fread($fp, self::ATTACHMENT_BLOCK_SIZE);
}
fclose($fp);
/* Exit to prevent output after the attachment. */
exit;
}
开发者ID:PublicityPort,项目名称:OpenCATS,代码行数:48,代码来源:AttachmentsUI.php
示例3: getInstance
function getInstance()
{
if (!isset(self::$instance[get_class()])) {
self::$instance = new Attachments();
}
return self::$instance;
}
开发者ID:reboxhost,项目名称:phpb2b,代码行数:7,代码来源:attachment.php
示例4: actionIndex
public function actionIndex()
{
$tagid = zmf::val('tagid', 2);
$tagInfo = array();
$default = true;
if ($tagid) {
$tagInfo = Tags::getByIds($tagid);
if ($tagInfo) {
$default = false;
$tagInfo = $tagInfo[0];
$sql = "SELECT p.id,p.uid,p.title,p.faceimg,p.content,p.tagids,p.comments,p.favorite FROM {{posts}} p,{{tag_relation}} tr WHERE tr.tagid='{$tagid}' AND tr.classify='posts' AND tr.logid=p.id AND p.`status`=" . Posts::STATUS_PASSED . " ORDER BY p.cTime DESC";
}
}
if ($default) {
$sql = 'SELECT id,uid,title,faceimg,content,tagids,comments,favorite FROM {{posts}} WHERE `status`=1 ORDER BY cTime DESC';
}
Posts::getAll(array('sql' => $sql), $pages, $posts);
$size = '640';
if ($this->isMobile) {
$size = '240';
}
foreach ($posts as $k => $val) {
if ($val['tagids'] != '') {
$_tags = Tags::getByIds($val['tagids']);
$posts[$k]['tagids'] = $_tags;
}
$posts[$k]['faceimg'] = Attachments::faceImg($val, $size);
}
$this->pageTitle = '文章 - ' . zmf::config('sitename');
$this->selectNav = 'posts';
$data = array('posts' => $posts, 'tagInfo' => $tagInfo, 'pages' => $pages);
$this->render('/index/index', $data);
}
开发者ID:ph7pal,项目名称:momo,代码行数:33,代码来源:IndexController.php
示例5: actionIndex
public function actionIndex()
{
if ($this->mySelf == 'yes') {
$sql = "SELECT id,title,faceimg,uid,colid,cTime,updateTime FROM {{posts}} WHERE (uid='{$this->uid}' OR uid IN(SELECT logid FROM {{favorites}} WHERE uid='{$this->uid}' AND classify='user')) AND classify='" . Posts::CLASSIFY_WEDDING . "' ORDER BY cTime DESC";
} else {
$sql = "SELECT id,title,faceimg,uid,colid,cTime,updateTime FROM {{posts}} WHERE uid='{$this->uid}' AND classify='" . Posts::CLASSIFY_WEDDING . "' ORDER BY cTime DESC";
}
Posts::getAll(array('sql' => $sql), $pages, $lists);
if (!empty($lists)) {
foreach ($lists as $k => $p) {
if ($p['faceimg'] > 0) {
$_attach = Attachments::getOne($p['faceimg']);
$_url = Attachments::getUrl($_attach);
$lists[$k]['faceimg'] = $_url;
} else {
$lists[$k]['faceimg'] = '';
}
}
}
if ($this->mySelf != 'yes') {
Posts::updateCount($this->uid, 'Users');
}
$data = array('posts' => $lists, 'pages' => $pages);
$this->pageTitle = $this->userInfo['truename'] . '的主页 - ' . zmf::config('sitename');
$this->render('index', $data);
}
开发者ID:ph7pal,项目名称:wedding,代码行数:26,代码来源:UsersController.php
示例6: getOne
/**
* 根据图片ID返回图片信息
* @param type $id
* @return boolean
*/
public static function getOne($id)
{
if (!$id || !is_numeric($id)) {
return false;
}
//todo,图片分表,将图片表分为attachments0~9
return Attachments::model()->findByPk($id);
}
开发者ID:ph7pal,项目名称:momo,代码行数:13,代码来源:Attachments.php
示例7: loadModel
/**
* Returns the data model based on the primary key given in the GET variable.
* If the data model is not found, an HTTP exception will be raised.
* @param integer $id the ID of the model to be loaded
* @return Attachments the loaded model
* @throws CHttpException
*/
public function loadModel($id)
{
$model = Attachments::model()->findByPk($id);
if ($model === null) {
throw new CHttpException(404, 'The requested page does not exist.');
}
return $model;
}
开发者ID:ph7pal,项目名称:mei,代码行数:15,代码来源:AttachmentsController.php
示例8: executeUpload
public function executeUpload(sfWebRequest $request)
{
$file = $request->getFiles();
$filename = mt_rand(111111, 999999) . '-' . $file['Filedata']['name'];
if (move_uploaded_file($file['Filedata']['tmp_name'], sfConfig::get('sf_upload_dir') . '/attachments/' . $filename)) {
$bind_id = $request->getParameter('bind_id');
if ((int) $bind_id == 0) {
$bind_id = -$this->getUser()->getAttribute('id');
}
$a = new Attachments();
$a->setFile($filename);
$a->setBindType($request->getParameter('bind_type'));
$a->setBindId($bind_id);
$a->save();
}
exit;
}
开发者ID:noikiy,项目名称:qdpm,代码行数:17,代码来源:actions.class.php
示例9: actionStat
public function actionStat()
{
$posts = Posts::model()->count();
$commentsNum = Comments::model()->count();
$attachsNum = Attachments::model()->count();
$feedbackNum = Feedback::model()->count();
$arr = array('posts' => $posts, 'commentsNum' => $commentsNum, 'attachsNum' => $attachsNum, 'feedbackNum' => $feedbackNum);
$this->render('stat', $arr);
}
开发者ID:ph7pal,项目名称:momo,代码行数:9,代码来源:IndexController.php
示例10: getAvatar
public static function getAvatar($aid, $size = 170)
{
$info = Attachments::getOne($aid);
$url = '';
if ($info) {
$url = zmf::uploadDirs($info['cTime'], 'site', $info['classify'], $size) . $info['filePath'];
}
return $url;
}
开发者ID:ph7pal,项目名称:wedding,代码行数:9,代码来源:WeddingGroup.php
示例11: executeAttachments
public function executeAttachments()
{
Attachments::clearTmpUploadedFiles($this->getUser());
$q = Doctrine_Core::getTable('Attachments')->createQuery()->addWhere('bind_id=?', $this->bind_id)->addWhere('bind_type=?', $this->bind_type)->orderBy('id');
if ($this->bind_id > 0) {
$q->addWhere("bind_id='" . $this->bind_id . "' or (bind_id='-" . $this->getUser()->getAttribute('id') . "')");
} else {
$q->addWhere("bind_id='-" . $this->getUser()->getAttribute('id') . "'");
}
$this->attachments = $q->execute();
}
开发者ID:noikiy,项目名称:qdpm,代码行数:11,代码来源:components.class.php
示例12: __construct
/**
* Constructor
*
* @param Request $request
* @return AttachmentsController
*/
function __construct($request)
{
parent::__construct($request);
$attachment_id = $this->request->getId('attachment_id');
if ($attachment_id) {
$this->active_attachment = Attachments::findById($attachment_id);
}
// if
if (!instance_of($this->active_attachment, 'Attachment')) {
$this->active_attachment = new Attachment();
}
// if
$this->smarty->assign(array('active_attachment' => $this->active_attachment));
}
开发者ID:NaszvadiG,项目名称:activecollab_loc,代码行数:20,代码来源:AttachmentsController.class.php
示例13: actionIndex
public function actionIndex()
{
$criteria = new CDbCriteria();
$criteria->order = 'cTime DESC';
$count = Attachments::model()->count($criteria);
$pager = new CPagination($count);
$pager->pageSize = 30;
$pager->applyLimit($criteria);
$posts = Attachments::model()->findAll($criteria);
foreach ($posts as $k => $val) {
$_img = Attachments::getUrl($val, 240);
$posts[$k]['filePath'] = $_img;
}
$this->render('index', array('pages' => $pager, 'posts' => $posts));
}
开发者ID:ph7pal,项目名称:momo,代码行数:15,代码来源:AttachmentsController.php
示例14: createZipFile
public function createZipFile(array $file_Ids, $filename)
{
$files = Attachments::query()->inWhere('attachable_id', $file_Ids)->andWhere('attachable_type =:type:', ['type' => 'Files'])->leftJoin('Files', 'file.id = Attachments.attachable_id', 'file')->columns(['Attachments.*', 'file.*'])->execute();
$path = 'E:\\php\\standard\\public/';
$zip = new ZipArchive();
if ($zip->open($path . $filename, ZIPARCHIVE::CREATE) !== TRUE) {
dd('无法生成ZIP文件,请检查是否具有写权限');
}
foreach ($files as $row) {
$zip->addFile($path . $row->attachments->url, $row->file->title . '/' . $row->attachments->name);
$zip->addFromString($row->file->title . '/info.txt', $this->getFileInfo($row->file));
//@todo 将来用能够代表文档的数据形式来替代
}
$zip->close();
return $filename;
}
开发者ID:huoybb,项目名称:standard,代码行数:16,代码来源:myDownload.php
示例15: __construct
/**
* Creates a new AttachmentsEditor object.
*
* @param integer $messageID
* @param string $isHash
* @param string $messageType
* @param integer $maxFileSize
* @param string $allowedExtensions
* @param integer $maxUploads
*/
public function __construct($messageID = 0, $messageType = 'post', $maxFileSize = 2000000, $allowedExtensions = "gif\njpg\njpeg\npng\nbmp\nzip\ntxt", $maxUploads = 5, $packageID = PACKAGE_ID, $thumbnailWidth = ATTACHMENT_THUMBNAIL_WIDTH, $thumbnailHeight = ATTACHMENT_THUMBNAIL_HEIGHT, $addSourceInfo = ATTACHMENT_THUMBNAIL_ADD_SOURCE_INFO, $useEmbedded = ATTACHMENT_THUMBNAIL_USE_EMBEDDED)
{
$this->messageID = $messageID;
$this->thumbnailWidth = $thumbnailWidth;
$this->thumbnailHeight = $thumbnailHeight;
$this->addSourceInfo = $addSourceInfo;
$this->useEmbedded = $useEmbedded;
if (empty($this->messageID)) {
$this->getIDHash();
}
// call parent constructor
parent::__construct($messageID ? $messageID : null, $messageType, $this->idHash, $packageID);
$this->maxFileSize = $maxFileSize;
$this->maxUploads = $maxUploads;
$allowedExtensions = StringUtil::unifyNewlines($allowedExtensions);
$allowedExtensions = implode("\n", array_unique(explode("\n", $allowedExtensions)));
$this->allowedExtensions = '/^(' . StringUtil::replace("\n", "|", StringUtil::replace('\\*', '.*', preg_quote($allowedExtensions, '/'))) . ')$/i';
$this->allowedExtensionsDesc = self::formatAllowedExtensions($allowedExtensions);
$this->getAttachmentHashes();
$this->assign();
}
开发者ID:joaocustodio,项目名称:EmuDevstore-1,代码行数:31,代码来源:AttachmentsEditor.class.php
示例16: doUserLogin
public function doUserLogin($user, $request)
{
$this->getUser()->setAttribute('id', $user->getId());
$this->getUser()->setAttribute('users_group_id', $user->getUsersGroupId());
$this->getUser()->setAttribute('user', $user);
$this->getUser()->setAuthenticated(true);
Attachments::clearTmpUploadedFiles($this->getUser());
$this->getUser()->setCulture($user->getCulture());
if (strlen($user->getSkin()) > 0) {
$this->getResponse()->setCookie('skin', $user->getSkin(), time() + 31536000, '', '');
}
$ug = $user->getUsersGroups();
if ($ug->getAllowManageProjects() > 0) {
$this->getUser()->addCredential('reports_access_projects');
}
if ($ug->getAllowManageTasks() > 0) {
$this->getUser()->addCredential('reports_access_tasks');
$this->getUser()->addCredential('reports_access_time');
$this->getUser()->addCredential('reports_access_time_personal');
$this->getUser()->addCredential('reports_access_gantt');
}
if ($ug->getAllowManageTickets() > 0) {
$this->getUser()->addCredential('reports_access_tickets');
}
if ($ug->getAllowManageDiscussions() > 0) {
$this->getUser()->addCredential('reports_access_discussions');
}
if ($ug->getAllowManageUsers() == 1) {
$this->getUser()->addCredential('allow_manage_users');
}
if ($ug->getAllowManageConfiguration() == 1) {
$this->getUser()->addCredential('allow_manage_configuration');
}
$this->getUser()->addCredential('allow_manage_personal_scheduler');
if (strlen($request->getParameter('http_referer')) > 0) {
$this->redirect($request->getParameter('http_referer'));
} else {
$this->redirect('dashboard/index');
}
}
开发者ID:noikiy,项目名称:qdpm,代码行数:40,代码来源:actions.class.php
示例17: actionCreate
public function actionCreate($id = '')
{
if (!$this->uid) {
$this->redirect(array('site/login'));
}
if ($id) {
$model = $this->loadModel($id);
} else {
$model = new SiteInfo();
}
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if (isset($_POST['SiteInfo'])) {
$filter = Posts::handleContent($_POST['SiteInfo']['content']);
$_POST['SiteInfo']['content'] = $filter['content'];
if (!empty($filter['attachids'])) {
$attkeys = array_filter(array_unique($filter['attachids']));
if (!empty($attkeys)) {
$_POST['SiteInfo']['faceimg'] = $attkeys[0];
//默认将文章中的第一张图作为封面图
}
}
$model->attributes = $_POST['SiteInfo'];
if ($model->save()) {
//将上传的图片置为通过
Attachments::model()->updateAll(array('status' => Posts::STATUS_DELED), 'logid=:logid AND classify=:classify', array(':logid' => $model->id, ':classify' => 'siteinfo'));
if (!empty($attkeys)) {
$attstr = join(',', $attkeys);
if ($attstr != '') {
Attachments::model()->updateAll(array('status' => Posts::STATUS_PASSED, 'logid' => $model->id), 'id IN(' . $attstr . ')');
}
}
$this->redirect(array('siteinfo/view', 'code' => $model->code));
}
}
$this->render('/site/createSiteInfo', array('model' => $model));
}
开发者ID:ph7pal,项目名称:mei,代码行数:37,代码来源:SiteinfoController.php
示例18: cleanUpByIds
/**
* Clean up system by object ID-s
*
* This function cleans up project objects recursively. It is also infinite
* loop safe because it will filter out ID-s that are already removed
*
* @param array $ids
* @return null
*/
function cleanUpByIds($ids)
{
static $cleaned_ids = array();
// Remove objects that are already cleaned
if (is_foreachable($ids)) {
foreach ($ids as $k => $id) {
if (isset($cleaned_ids[$id]) && $cleaned_ids[$id]) {
unset($ids[$k]);
} else {
$cleaned_ids[$id] = false;
}
// if
}
// foreach
}
// if
if (is_foreachable($ids)) {
db_begin_work();
Attachments::deleteByProjectObjectIds($ids);
Subscriptions::deleteByObjectIds($ids);
Assignments::deleteByObjectIds($ids);
ActivityLogs::deleteByObjectIds($ids);
StarredObjects::deleteByObjectIds($ids);
Reminders::deleteByObjectIds($ids);
search_index_remove($ids, 'ProjectObject');
$rows = db_execute_all('SELECT DISTINCT id FROM ' . TABLE_PREFIX . 'project_objects WHERE parent_id IN (?)', $ids);
if (is_foreachable($rows)) {
$subobject_ids = array();
foreach ($rows as $row) {
$subobject_ids[] = (int) $row['id'];
}
// foreach
ProjectObjects::cleanUpByIds($subobject_ids);
}
// if
ProjectObjects::delete(array('id IN (?)', $ids));
foreach ($ids as $id) {
$cleaned_ids[$id] = true;
}
// if
db_commit();
}
// if
return true;
}
开发者ID:NaszvadiG,项目名称:activecollab_loc,代码行数:54,代码来源:ProjectObjects.class.php
示例19: SecureAJAXInterface
* (or from the year in which this file was created to the year 2007) by
* Cognizo Technologies, Inc. All Rights Reserved.
*
*
* $Id: getAttachmentLocal.php 3078 2007-09-21 20:25:28Z will $
*/
$interface = new SecureAJAXInterface();
include_once './lib/CommonErrors.php';
include_once './lib/Attachments.php';
@ini_set('memory_limit', '256M');
if (!isset($_POST['id']) || !$interface->isRequiredIDValid('id')) {
$interface->outputXMLErrorPage(-2, 'No attachment ID specified.');
die;
}
$attachmentID = $_POST['id'];
$attachments = new Attachments(-1);
$rs = $attachments->get($attachmentID, false);
if (!isset($rs['directoryName']) || !isset($rs['storedFilename']) || md5($rs['directoryName']) != $_POST['directoryNameHash']) {
$interface->outputXMLErrorPage(-2, 'Invalid directory name hash.');
die;
}
$directoryName = $rs['directoryName'];
$fileName = $rs['storedFilename'];
/* Check for the existence of the backup. If it is gone, send the user to a page informing them to press back and generate the backup again. */
if ($rs['contentType'] == 'catsbackup') {
if (!file_exists('attachments/' . $directoryName . '/' . $fileName)) {
$interface->outputXMLErrorPage(-2, 'The specified backup file no longer exists. Please press back and regenerate the backup before downloading. We are sorry for the inconvenience.');
die;
}
}
$url = 'attachments/' . $directoryName . '/' . $fileName;
开发者ID:PublicityPort,项目名称:OpenCATS,代码行数:31,代码来源:getAttachmentLocal.php
示例20: renderFormFieldByType
public static function renderFormFieldByType($f, $values)
{
$value = isset($values[$f['id']]) ? $values[$f['id']] : '';
$attributes = array();
switch ($f['type']) {
case 'file':
$html = '';
if ($value > 0) {
if ($a = Doctrine_Core::getTable('Attachments')->find($value)) {
$html = '<br>' . Attachments::getLink($a) . input_hidden_tag('extra_fields_files[' . $f['id'] . ']', $value) . '<br>' . input_checkbox_tag('extra_fields_files_delete[' . $f['id'] . ']', $value) . ' <label for="extra_fields_files_delete_' . $f['id'] . '">' . __('Delete') . '</label>';
$attributes['class'] = '';
}
}
return input_file_tag('extra_fields[' . $f['id'] . ']', '', $attributes) . $html;
break;
case 'number':
return input_tag('extra_fields[' . $f['id'] . ']', $value, $attributes);
break;
case 'text':
case 'url':
$attributes['size'] = '40';
return input_tag('extra_fields[' . $f['id'] . ']', $value, $attributes);
break;
case 'textarea':
return textarea_tag('extra_fields[' . $f['id'] . ']', $value, $attributes);
break;
case 'textarea_wysiwyg':
if (isset($attributes['class'])) {
$attributes['class'] .= ' editor';
} else {
$attributes['class'] = 'editor';
}
return textarea_tag('extra_fields[' . $f['id'] . ']', $value, $attributes);
break;
case 'date':
if (isset($attributes['class'])) {
$attributes['class'] .= ' datepicker';
} else {
$attributes['class'] = 'datepicker';
}
$attributes['size'] = '11';
return input_tag('extra_fields[' . $f['id'] . ']', $value, $attributes);
break;
case 'date_range':
if (isset($attributes['class'])) {
$attributes['class'] .= ' datepicker';
} else {
$attributes['class'] = 'datepicker';
}
$attributes['size'] = '11';
if (strlen($value) > 0) {
$value = explode('|', $value);
} else {
$value = array('', '');
}
return __('From') . ': ' . input_tag('extra_fields[' . $f['id'] . '][from]', $value[0], $attributes) . ' ' . __('To') . ': ' . input_tag('extra_fields[' . $f['id'] . '][to]', $value[1], $attributes);
break;
case 'date_time':
if (isset($attributes['class'])) {
$attributes['class'] .= ' datetimepicker';
} else {
$attributes['class'] = 'datetimepicker';
}
$attributes['size'] = '17';
return input_tag('extra_fields[' . $f['id'] . ']', $value, $attributes);
break;
case 'date_dropdown':
$years = range(date('Y') - 100, date('Y') + 20);
$w = new sfWidgetFormDate(array('years' => array_combine($years, $years), 'format' => __('Year') . ':%year% ' . __('Month') . ':%month% ' . __('Day') . ':%day%'));
return $w->render('extra_fields[' . $f['id'] . ']', $value, $attributes);
break;
case 'pull_down':
$choices = array();
foreach (explode("\n", $f['default_values']) as $v) {
$choices[trim($v)] = trim($v);
}
return select_tag('extra_fields[' . $f['id'] . ']', $value, array('choices' => $choices), $attributes);
break;
case 'checkbox':
$choices = array();
foreach (explode("\n", $f['default_values']) as $v) {
$choices[trim($v)] = trim($v);
}
return '<div id="checkboxesList' . $f['id'] . '" class="checkboxesList">' . select_tag('extra_fields[' . $f['id'] . ']', explode("\n", $value), array('choices' => $choices, 'expanded' => true, 'multiple' => true), $attributes) . '</div>';
break;
case 'radiobox':
$choices = array();
foreach (explode("\n", $f['default_values']) as $v) {
$choices[trim($v)] = trim($v);
}
return select_tag('extra_fields[' . $f['id'] . ']', $value, array('choices' => $choices, 'expanded' => true), $attributes);
break;
}
}
开发者ID:noikiy,项目名称:qdpm,代码行数:94,代码来源:ExtraFieldsList.class.php
注:本文中的Attachments类示例整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论