diff --git a/extensions/debug/CHANGELOG.md b/extensions/debug/CHANGELOG.md index 6f869b2..038586a 100644 --- a/extensions/debug/CHANGELOG.md +++ b/extensions/debug/CHANGELOG.md @@ -8,6 +8,7 @@ Yii Framework 2 debug extension Change Log - Bug #1504: Debug toolbar isn't loaded successfully in some environments when xdebug is enabled (qiangxue) - Bug #1747: Fixed problems with displaying toolbar on small screens (cebe) - Bug #1827: Debugger toolbar is loaded twice if an action is calling `run()` to execute another action (qiangxue) +- Enh #1667: Added mail panel (Ragazzo, 6pblcb) - Enh #2006: Added total queries count monitoring (o-rey, Ragazzo) 2.0.0 alpha, December 1, 2013 diff --git a/extensions/debug/Module.php b/extensions/debug/Module.php index ae166bd..c475387 100644 --- a/extensions/debug/Module.php +++ b/extensions/debug/Module.php @@ -161,6 +161,7 @@ class Module extends \yii\base\Module 'log' => ['class' => 'yii\debug\panels\LogPanel'], 'profiling' => ['class' => 'yii\debug\panels\ProfilingPanel'], 'db' => ['class' => 'yii\debug\panels\DbPanel'], + 'mail' => ['class' => 'yii\debug\panels\MailPanel'], ]; } } diff --git a/extensions/debug/assets/main.css b/extensions/debug/assets/main.css index 54babe7..c881ca8 100644 --- a/extensions/debug/assets/main.css +++ b/extensions/debug/assets/main.css @@ -73,3 +73,14 @@ a.desc:after { .sort-ordinal a.desc:after { content: "\e156"; } + +.mail-sorter { + margin-top: 7px; +} + +.mail-sorter li { + list-style: none; + float: left; + width: 12%; + font-weight: bold; +} diff --git a/extensions/debug/controllers/DefaultController.php b/extensions/debug/controllers/DefaultController.php index c2ef235..9f64d40 100644 --- a/extensions/debug/controllers/DefaultController.php +++ b/extensions/debug/controllers/DefaultController.php @@ -93,6 +93,16 @@ class DefaultController extends Controller ]); } + public function actionDownloadMail($file) + { + $filePath = Yii::getAlias($this->module->panels['mail']->mailPath) . '/' . basename($file); + + if ((mb_strpos($file, '\\') !== false || mb_strpos($file, '/') !== false) || !is_file($filePath)) { + throw new NotFoundHttpException('Mail file not found'); + } + + Yii::$app->response->sendFile($filePath); + } private $_manifest; diff --git a/extensions/debug/models/search/Mail.php b/extensions/debug/models/search/Mail.php new file mode 100644 index 0000000..59d310c --- /dev/null +++ b/extensions/debug/models/search/Mail.php @@ -0,0 +1,121 @@ +<?php + +namespace yii\debug\models\search; + +use yii\data\ArrayDataProvider; +use yii\debug\components\search\Filter; + +/** + * Mail represents the model behind the search form about current send emails. + */ +class Mail extends Base +{ + /** + * @var string from attribute input search value + */ + public $from; + + /** + * @var string to attribute input search value + */ + public $to; + + /** + * @var string reply attribute input search value + */ + public $reply; + + /** + * @var string cc attribute input search value + */ + public $cc; + + /** + * @var string bcc attribute input search value + */ + public $bcc; + + /** + * @var string subject attribute input search value + */ + public $subject; + + /** + * @var string body attribute input search value + */ + public $body; + + /** + * @var string charset attribute input search value + */ + public $charset; + + /** + * @var string headers attribute input search value + */ + public $headers; + + /** + * @var string file attribute input search value + */ + public $file; + + public function rules() + { + return [ + [['from', 'to', 'reply', 'cc', 'bcc', 'subject', 'body', 'charset'], 'safe'], + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'from' => 'From', + 'to' => 'To', + 'reply' => 'Reply', + 'cc' => 'Copy receiver', + 'bcc' => 'Hidden copy receiver', + 'subject' => 'Subject', + 'charset' => 'Charset' + ]; + } + + /** + * Returns data provider with filled models. Filter applied if needed. + * @param array $params + * @param array $models + * @return \yii\data\ArrayDataProvider + */ + public function search($params, $models) + { + $dataProvider = new ArrayDataProvider([ + 'allModels' => $models, + 'pagination' => [ + 'pageSize' => 5, + ], + 'sort' => [ + 'attributes' => ['from', 'to', 'reply', 'cc', 'bcc', 'subject', 'body', 'charset'], + ], + ]); + + if (!($this->load($params) && $this->validate())) { + return $dataProvider; + } + + $filter = new Filter(); + $this->addCondition($filter, 'from', true); + $this->addCondition($filter, 'to', true); + $this->addCondition($filter, 'reply', true); + $this->addCondition($filter, 'cc', true); + $this->addCondition($filter, 'bcc', true); + $this->addCondition($filter, 'subject', true); + $this->addCondition($filter, 'body', true); + $this->addCondition($filter, 'charset', true); + $dataProvider->allModels = $filter->filter($models); + + return $dataProvider; + } +} diff --git a/extensions/debug/panels/MailPanel.php b/extensions/debug/panels/MailPanel.php new file mode 100644 index 0000000..85ed504 --- /dev/null +++ b/extensions/debug/panels/MailPanel.php @@ -0,0 +1,91 @@ +<?php + +namespace yii\debug\panels; + +use Yii; +use yii\base\Event; +use yii\debug\models\search\Mail; +use yii\debug\Panel; +use yii\mail\BaseMailer; +use yii\helpers\FileHelper; + +/** + * Debugger panel that collects and displays the generated emails. + */ +class MailPanel extends Panel +{ + + /** + * @var string path where all mails will be saved. should be an alias. + */ + public $mailPath = '@runtime/debug/mail'; + /** + * @var array current request sent messages + */ + private $_messages = []; + + public function init() + { + parent::init(); + Event::on(BaseMailer::className(), BaseMailer::EVENT_AFTER_SEND, function ($event) { + + $message = $event->message->getSwiftMessage(); + $textBody = $message->getBody(); + $fileName = $event->sender->generateMessageFileName(); + + FileHelper::createDirectory(Yii::getAlias($this->mailPath)); + file_put_contents(Yii::getAlias($this->mailPath) . '/' . $fileName, $message->toString()); + + $this->_messages[] = [ + 'isSuccessful' => $event->isSuccessful, + 'time' => $message->getDate(), + 'headers' => $message->getHeaders(), + 'from' => $this->convertParams($message->getFrom()), + 'to' => $this->convertParams($message->getTo()), + 'reply' => $this->convertParams($message->getReplyTo()), + 'cc' => $this->convertParams($message->getCc()), + 'bcc' => $this->convertParams($message->getBcc()), + 'subject' => $message->getSubject(), + 'body' => $textBody, + 'charset' => $message->getCharset(), + 'file' => $fileName, + ]; + }); + } + + public function getName() + { + return 'Mail'; + } + + public function getSummary() + { + return Yii::$app->view->render('panels/mail/summary', ['panel' => $this, 'mailCount' => count($this->data)]); + } + + public function getDetail() + { + $searchModel = new Mail(); + $dataProvider = $searchModel->search(Yii::$app->request->get(), $this->data); + + return Yii::$app->view->render('panels/mail/detail', [ + 'panel' => $this, + 'dataProvider' => $dataProvider, + 'searchModel' => $searchModel + ]); + } + + public function save() + { + return $this->_messages; + } + + private function convertParams($attr) + { + if (is_array($attr)) { + $attr = implode(', ', array_keys($attr)); + } + return $attr; + } + +} diff --git a/extensions/debug/views/default/panels/mail/_item.php b/extensions/debug/views/default/panels/mail/_item.php new file mode 100644 index 0000000..fd485c9 --- /dev/null +++ b/extensions/debug/views/default/panels/mail/_item.php @@ -0,0 +1,38 @@ +<?php + +use yii\helpers\Html; +use yii\widgets\DetailView; + +$timeFormatter = extension_loaded('intl') ? Yii::createObject(['class' => 'yii\i18n\Formatter']) : Yii::$app->formatter; + +echo DetailView::widget([ + 'model' => $model, + 'attributes' => [ + 'headers', + 'from', + 'to', + 'charset', + [ + 'name' => 'time', + 'value' => $timeFormatter->asDateTime($model['time'], 'short'), + ], + 'subject', + [ + 'name' => 'body', + 'label' => 'Text body', + ], + [ + 'name' => 'isSuccessful', + 'label' => 'Successfully sent', + 'value' => $model['isSuccessful'] ? 'Yes' : 'No' + ], + 'reply', + 'bcc', + 'cc', + [ + 'name' => 'file', + 'format' => 'html', + 'value' => Html::a('Download eml', ['download-mail', 'file' => $model['file']]), + ], + ], +]); diff --git a/extensions/debug/views/default/panels/mail/detail.php b/extensions/debug/views/default/panels/mail/detail.php new file mode 100644 index 0000000..59d0d13 --- /dev/null +++ b/extensions/debug/views/default/panels/mail/detail.php @@ -0,0 +1,55 @@ +<?php +use \yii\widgets\ListView; +use yii\widgets\ActiveForm; +use yii\helpers\Html; + +$listView = new ListView([ + 'dataProvider' => $dataProvider, + 'itemView' => 'panels/mail/_item', + 'layout' => "{summary}\n{items}\n{pager}\n", + ]); +$listView->sorter = ['options' => ['class'=>'mail-sorter']]; +?> + +<h1>Email messages</h1> + +<div class="row"> + <div class="col-lg-2"> + <?= Html::button('Form filtering', ['class' => 'btn btn-default', 'onclick'=>'$("#email-form").toggle();']) ?> + </div> + <div class="row col-lg-10"> + <?= $listView->renderSorter() ?> + </div> +</div> + +<div id="email-form" style="display: none;"> + <?php $form = ActiveForm::begin([ + 'method' => 'get', + 'action' => ['/debug/default/view', 'tag'=>\Yii::$app->request->get('tag'), 'panel'=>'mail'], + ]); ?> + <div class="row"> + <?= $form->field($searchModel, 'from', ['options'=>['class'=>'col-lg-6']])->textInput() ?> + + <?= $form->field($searchModel, 'to', ['options'=>['class'=>'col-lg-6']])->textInput() ?> + + <?= $form->field($searchModel, 'reply', ['options'=>['class'=>'col-lg-6']])->textInput() ?> + + <?= $form->field($searchModel, 'cc', ['options'=>['class'=>'col-lg-6']])->textInput() ?> + + <?= $form->field($searchModel, 'bcc', ['options'=>['class'=>'col-lg-6']])->textInput() ?> + + <?= $form->field($searchModel, 'charset', ['options'=>['class'=>'col-lg-6']])->textInput() ?> + + <?= $form->field($searchModel, 'subject', ['options'=>['class'=>'col-lg-6']])->textInput() ?> + + <?= $form->field($searchModel, 'body', ['options'=>['class'=>'col-lg-6']])->textInput() ?> + + <div class="form-group col-lg-12"> + <?= Html::submitButton('Filter', ['class' => 'btn btn-success']) ?> + </div> + </div> + + <?php ActiveForm::end(); ?> +</div> + +<?= $listView->run() ?> diff --git a/extensions/debug/views/default/panels/mail/summary.php b/extensions/debug/views/default/panels/mail/summary.php new file mode 100644 index 0000000..4e35ff8 --- /dev/null +++ b/extensions/debug/views/default/panels/mail/summary.php @@ -0,0 +1,9 @@ +<?php +/** + * @var yii\debug\panels\MailPanel $panel + */ +if ($mailCount): ?> +<div class="yii-debug-toolbar-block"> + <a href="<?= $panel->getUrl() ?>">Mail <span class="label"><?= $mailCount ?></span></a> +</div> +<?php endif ?>