Browse Source

Fix errors on missing action/template error page.

Render a proper error page when a mailer raises a missing
template/action exception.

Refs #8706
Mark Story 9 years ago
parent
commit
190caaf141

+ 23 - 8
src/Template/Error/missing_action.ctp

@@ -26,18 +26,33 @@ if (!empty($prefix)) {
     $prefixNs = '\\' . $prefix;
     $prefix .= DIRECTORY_SEPARATOR;
 }
+
+// Cake\Controller\Exception\MissingActionException support
+if (isset($controller)) {
+    $baseClass = $namespace . '\Controller\AppController';
+    $extends = 'AppController';
+    $type = 'Controller';
+    $class = $controller;
+}
+// Cake\Mailer\Exception\MissingActionException support
+if (isset($mailer)) {
+    $baseClass = 'Cake\Mailer\Mailer';
+    $type = $extends = 'Mailer';
+    $class = $mailer;
+}
+
 if (empty($plugin)) {
-    $path = APP_DIR . DIRECTORY_SEPARATOR . 'Controller' . DIRECTORY_SEPARATOR . $prefix . h($controller) . '.php' ;
+    $path = APP_DIR . DIRECTORY_SEPARATOR . $type . DIRECTORY_SEPARATOR . $prefix . h($class) . '.php' ;
 } else {
-    $path = Plugin::classPath($plugin) . 'Controller' . DIRECTORY_SEPARATOR . $prefix . h($controller) . '.php';
+    $path = Plugin::classPath($plugin) . $type . DIRECTORY_SEPARATOR . $prefix . h($class) . '.php';
 }
 
 $this->layout = 'dev_error';
 
-$this->assign('title', sprintf('Missing Method in %s', h($controller)));
+$this->assign('title', sprintf('Missing Method in %s', h($class)));
 $this->assign(
     'subheading',
-    sprintf('The action <em>%s</em> is not defined in <em>%s</em>', h($action), h($controller))
+    sprintf('The action <em>%s</em> is not defined in <em>%s</em>', h($action), h($class))
 );
 $this->assign('templateName', 'missing_action.ctp');
 
@@ -45,17 +60,17 @@ $this->start('file');
 ?>
 <p class="error">
     <strong>Error: </strong>
-    <?= sprintf('Create <em>%s::%s()</em> in file: %s.', h($controller),  h($action), $path); ?>
+    <?= sprintf('Create <em>%s::%s()</em> in file: %s.', h($class),  h($action), $path); ?>
 </p>
 
 <?php
 $code = <<<PHP
 <?php
-namespace {$namespace}\Controller{$prefixNs};
+namespace {$namespace}\\{$type}{$prefixNs};
 
-use {$namespace}\Controller\AppController;
+use {$baseClass};
 
-class {$controller} extends AppController
+class {$class} extends {$extends}
 {
 
     public function {$action}()

+ 7 - 0
src/Template/Error/missing_template.ctp

@@ -19,10 +19,17 @@ $this->layout = 'dev_error';
 $this->assign('title', 'Missing Template');
 $this->assign('templateName', 'missing_template.ctp');
 
+$isEmail = strpos($file, 'Email/') === 0;
+
 $this->start('subheading');
 ?>
+<?php if ($isEmail): ?>
+    <strong>Error: </strong>
+    <?= sprintf('The template %s</em> was not found.', h($file)); ?>
+<?php else: ?>
     <strong>Error: </strong>
     <?= sprintf('The view for <em>%sController::%s()</em> was not found.', h(Inflector::camelize($this->request->controller)), h($this->request->action)); ?>
+<?php endif ?>
 <?php $this->end() ?>
 
 <?php $this->start('file') ?>

+ 14 - 0
tests/TestCase/Error/ExceptionRendererTest.php

@@ -27,6 +27,7 @@ use Cake\Datasource\Exception\MissingDatasourceException;
 use Cake\Error\ExceptionRenderer;
 use Cake\Event\Event;
 use Cake\Event\EventManager;
+use Cake\Mailer\Exception\MissingActionException as MissingMailerActionException;
 use Cake\Network\Exception\InternalErrorException;
 use Cake\Network\Exception\MethodNotAllowedException;
 use Cake\Network\Exception\NotFoundException;
@@ -584,6 +585,19 @@ class ExceptionRendererTest extends TestCase
                 500
             ],
             [
+                new MissingMailerActionException([
+                    'mailer' => 'UserMailer',
+                    'action' => 'welcome',
+                    'prefix' => '',
+                    'plugin' => '',
+                ]),
+                [
+                    '/Missing Method in UserMailer/',
+                    '/<em>UserMailer::welcome\(\)<\/em>/'
+                ],
+                404
+            ],
+            [
                 new Exception('boom'),
                 [
                     '/Internal Error/'