在一页中,我用// Copyright (c) 2019 Francesco Pretto
// This file is subject to the Apache License Version 2.0
#include "XFileAppender.h"
#include <log4cxx/helpers/synchronized.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/bufferedwriter.h>
#include <log4cxx/helpers/bytebuffer.h>
#include <log4cxx/helpers/fileoutputstream.h>
using namespace std;
using namespace log4cxx;
using namespace log4cxx::spi;
using namespace log4cxx::helpers;
static Pool s_pool;
Mutex XFileAppender::s_mutex(s_pool);
unordered_map<LogString, XFileAppender::AppenderIdentities> XFileAppender::s_appenderIdentities;
XFileAppender::XFileAppender()
{
m_failedWriter = false;
}
void XFileAppender::close()
{
synchronized sync(mutex);
if (closed)
return;
closeWriters();
closed = true;
}
void XFileAppender::append(const LoggingEventPtr &event, Pool &p)
{
InstanceWriter::Ptr instance;
{
synchronized sync(mutex);
if (closed)
return;
instance = getInstanceWriter(p);
if (instance == nullptr)
{
// Try to use non instanced writer
if (m_failedWriter)
return;
if (m_writer == nullptr)
{
m_writer = createWriter(LogString(), p);
if (m_writer == nullptr)
{
m_failedWriter = true;
return;
}
}
LogString msg;
layout->format(msg, event, p);
m_writer->write(msg, p);
if (getImmediateFlush())
m_writer->flush(p);
return;
}
}
// NOTE: From now, we can release the appender istance lock
if (instance->Writer == nullptr)
{
// This is a failed writer
return;
}
LogString msg;
layout->format(msg, event, p);
synchronized syncWriter(instance->Mutex);
instance->Writer->write(msg, p);
if (getImmediateFlush())
instance->Writer->flush(p);
}
void XFileAppender::activateOptions(helpers::Pool &p)
{
synchronized syncWriter(mutex);
closeWriters();
// Do nothing more. We lazily create writers later
}
void XFileAppender::ClearWriters()
{
synchronized lock(s_mutex);
s_appenderIdentities.clear();
}
void XFileAppender::closeWriter(InstanceWriter &writer)
{
synchronized syncWriter(writer.Mutex);
// If it's a valid writer. It could be a failed one
if (writer.Writer != nullptr)
closeWriter(*writer.Writer);
}
// Stripped from WriterAppender.cpp
void XFileAppender::closeWriter(Writer &writer)
{
try
{
// before closing we have to output out layout's footer
// NOTE: Using the object's pool since this is a one-shot operation and
// pool is likely to be reclaimed soon when appender is destructed.
if (layout != NULL)
{
LogString foot;
layout->appendFooter(foot, pool);
writer.write(foot, pool);
}
writer.close(pool);
}
catch (IOException& e)
{
LogLog::error(LogString(LOG4CXX_STR("Could not close writer for WriterAppender named ")) + name, e);
}
}
void XFileAppender::closeWriters()
{
vector<LogString> instancesToDelete;
for (auto &pair : m_instanceWriters)
{
auto &writer = pair.second;
closeWriter(*writer->Writer);
instancesToDelete.push_back(pair.first);
}
removeAppenderIstances(getName(), instancesToDelete);
m_instanceWriters.clear();
if (m_writer != nullptr)
{
closeWriter(*m_writer);
m_writer = nullptr;
}
}
// Stripped from FileAppender.cpp
WriterPtr XFileAppender::createWriter(const LogString &instanceid, helpers::Pool& p)
{
LogString fileName = getFile();
if (fileName.empty())
{
LogLog::error(LogString(LOG4CXX_STR("File option not set for appender ["))
+ name + LOG4CXX_STR("]."));
LogLog::warn(LOG4CXX_STR("Are you using FileAppender instead of ConsoleAppender?"));
return nullptr;
}
File file(fileName);
if (instanceid.length() != 0)
{
auto name = file.getName();
auto parent = file.getParent(p);
#if WIN32
file = parent + LOG4CXX_STR("\\") + instanceid + LOG4CXX_STR("_") + name;
#else
file = parent + LOG4CXX_STR("/") + instanceid + LOG4CXX_STR("_") + name;
#endif
}
try
{
return createWriter(file, p);
}
catch (IOException& e)
{
LogString msg(LOG4CXX_STR("createWriter("));
msg.append(fileName);
msg.append(1, (logchar)0x2C /* ',' */);
StringHelper::toString(fileAppend, msg);
msg.append(LOG4CXX_STR(") call failed."));
errorHandler->error(msg, e, ErrorCode::FILE_OPEN_FAILURE);
return nullptr;
}
}
// Stripped from FileAppender.cpp
WriterPtr XFileAppender::createWriter(const File &outFile, helpers::Pool& p)
{
bool append = getAppend();
bool writeBOM = false;
if (StringHelper::equalsIgnoreCase(getEncoding(),
LOG4CXX_STR("utf-16"), LOG4CXX_STR("UTF-16")))
{
// don't want to write a byte order mark if the file exists
if (append)
{
writeBOM = !outFile.exists(p);
}
else
{
writeBOM = true;
}
}
OutputStreamPtr outStream;
try
{
outStream = new FileOutputStream(outFile.getPath(), append);
}
catch (IOException& ex)
{
LogString parentName = outFile.getParent(p);
if (!parentName.empty())
{
File parentDir;
parentDir.setPath(parentName);
if (!parentDir.exists(p) && parentDir.mkdirs(p))
{
outStream = new FileOutputStream(outFile.getPath(), append);
}
else
{
throw;
}
}
else
{
throw;
}
}
// if a new file and UTF-16, then write a BOM
if (writeBOM)
{
char bom[] = { (char)0xFE, (char)0xFF };
ByteBuffer buf(bom, 2);
outStream->write(buf, p);
}
WriterPtr newWriter(WriterAppender::createWriter(outStream));
if (getBufferedIO())
{
newWriter = new BufferedWriter(newWriter, getBufferSize());
}
if (layout != NULL)
{
LogString header;
layout->appendHeader(header, p);
newWriter->write(header, p);
}
return newWriter;
}
void XFileAppender::removeAppenderIstances(const LogString &appname, vector<LogString> &instanceIds)
{
synchronized lock(s_mutex);
if (s_appenderIdentities.size() == 0)
return;
for (auto &instanceid : instanceIds)
{
auto found = s_appenderIdentities.find(instanceid);
if (found == s_appenderIdentities.end())
break;
found->second.erase(appname);
if (found->second.size() == 0)
{
// All appenders for this instance were closed
s_appenderIdentities.erase(found);
}
}
}
XFileAppender::InstanceWriter::Ptr XFileAppender::getInstanceWriter(Pool &p)
{
LogString instanceid = MDC::get(LOG4CXX_STR("__ITRInstanceId"));
if (instanceid.length() == 0)
return nullptr;
auto &writer = m_instanceWriters[instanceid];
if (writer == nullptr)
{
// NOTE: We must use instance pool here otherwise there are
// crashes, don't know exactly why
writer.reset(new InstanceWriter(pool));
writer->Writer = createWriter(instanceid, p);
synchronized lock(s_mutex);
auto &appenders = s_appenderIdentities[instanceid];
appenders[getName()] = this;
}
return writer;
}
void XFileAppender::CloseIstanceWriters(const LogString &instanceid)
{
synchronized lock(s_mutex);
auto found = s_appenderIdentities.find(instanceid);
if (found == s_appenderIdentities.end())
return;
for (auto &pair : found->second)
{
auto appender = pair.second;
appender->CloseWriter(instanceid);
}
s_appenderIdentities.erase(found);
}
void XFileAppender::CloseWriter(const LogString &istanceid)
{
synchronized sync(mutex);
auto found = m_instanceWriters.find(istanceid);
closeWriter(*found->second);
m_instanceWriters.erase(found);
}
XFileAppender::InstanceWriter::InstanceWriter(Pool &p)
: Mutex(p) { }
IMPLEMENT_LOG4CXX_OBJECT(XFileAppender)
的形式渲染另一页,如果在关闭模式(不提交)的情况下填充输入,则仅单击(x)就能在再次打开模式时保持输入的值吗?
索引,php
bootstrap modal
.js
<?= Html::a('<button class="btn btn-info">+</button>',['app/create'], ['id' => 'btn-add']) ?>
<?php
Modal::begin([
'header' => '<div id="modal-title"></div>',
'id' => 'modal',
'size' => 'modal-lg',
'clientOptions' => ['backdrop' => 'static', 'keyboard' => false],
]);
echo "<div id='modalContent'></div>";
Modal::end();
?>
答案 0 :(得分:1)
您正在使用jquery .load()
方法将表单加载到模式窗口内,并且无论您单击模式按钮上的关闭按钮还是覆盖背景,当再次单击按钮+
时,都将加载内容再次出现在模式窗口中。
因此,如果您确实要这样做,则必须将表单移到具有Modal
代码的同一视图内,这意味着您必须内联添加表单并将javascript按钮更改为{ {1}}。应该是下面的样子
$('#modal').modal('show')
您的Js应该简单
<?= Html::a('<button class="btn btn-info">+</button>','#', ['id' => 'btn-add']) ?>
<?php
Modal::begin([
'header' => '<div id="modal-title"></div>',
'id' => 'modal',
'size' => 'modal-lg',
'clientOptions' => ['backdrop' => 'static', 'keyboard' => false],
]);?>
<div id='modalContent'>
<?php
//your active form starts here
$form = ActiveForm::begin(
[
'id' => 'your-form-id',
'action' => Url::to(['/controller/action'])
]
);
?>
<?php
ActiveForm::end();
?>
</div>
<?php Modal::end();
?>