1: <?php
  2: 
  3: namespace Charcoal\App\Handler;
  4: 
  5: 
  6: use Psr\Http\Message\ServerRequestInterface;
  7: use Psr\Http\Message\ResponseInterface;
  8: 
  9: 
 10: use Slim\Http\Body;
 11: 
 12: 
 13: use Charcoal\App\Handler\AbstractHandler;
 14: 
 15:  16:  17:  18:  19:  20:  21:  22: 
 23: class NotAllowed extends AbstractHandler
 24: {
 25:      26:  27:  28:  29: 
 30:     protected $methods;
 31: 
 32:      33:  34:  35:  36:  37:  38:  39: 
 40:     public function __invoke(ServerRequestInterface $request, ResponseInterface $response, array $methods)
 41:     {
 42:         $this->setMethods($methods);
 43: 
 44:         if ($request->getMethod() === 'OPTIONS') {
 45:             $status = 200;
 46:             $contentType = 'text/plain';
 47:             $output = $this->renderPlainOutput();
 48:         } else {
 49:             $status = 405;
 50:             $contentType = $this->determineContentType($request);
 51:             switch ($contentType) {
 52:                 case 'application/json':
 53:                     $output = $this->renderJsonOutput();
 54:                     break;
 55: 
 56:                 case 'text/xml':
 57:                 case 'application/xml':
 58:                     $output = $this->renderXmlOutput();
 59:                     break;
 60: 
 61:                 case 'text/html':
 62:                 default:
 63:                     $output = $this->renderHtmlOutput();
 64:                     break;
 65:             }
 66:         }
 67: 
 68:         $body = new Body(fopen('php://temp', 'r+'));
 69:         $body->write($output);
 70:         $allow = implode(', ', $methods);
 71: 
 72:         return $response
 73:                 ->withStatus($status)
 74:                 ->withHeader('Content-type', $contentType)
 75:                 ->withHeader('Allow', $allow)
 76:                 ->withBody($body);
 77:     }
 78: 
 79:      80:  81:  82:  83:  84: 
 85:     protected function setMethods(array $methods)
 86:     {
 87:         $this->methods = implode(', ', $methods);
 88: 
 89:         return $this;
 90:     }
 91: 
 92:      93:  94:  95:  96: 
 97:     public function methods()
 98:     {
 99:         return $this->methods;
100:     }
101: 
102:     103: 104: 105: 106: 
107:     protected function renderPlainOutput()
108:     {
109:         $message = $this->translator()->translate('Allowed methods:').' '.$this->methods();
110: 
111:         return $this->render($message);
112:     }
113: 
114:     115: 116: 117: 118: 
119:     protected function renderJsonOutput()
120:     {
121:         $message = $this->translator()->translate('Method not allowed. Must be one of:').' '.$this->methods();
122: 
123:         return $this->render('{"message":"'.$message.'"}');
124:     }
125: 
126:     127: 128: 129: 130: 
131:     protected function renderXmlOutput()
132:     {
133:         $message = $this->translator()->translate('Method not allowed. Must be one of:').' '.$this->methods();
134: 
135:         return $this->render('<root><message>'.$message.'</message></root>');
136:     }
137: 
138:     139: 140: 141: 142: 
143:     public function messageTitle()
144:     {
145:         return $this->translator()->translate('Method not allowed.');
146:     }
147: 
148:     149: 150: 151: 152: 
153:     public function renderHtmlMessage()
154:     {
155:         $title   = $this->messageTitle();
156:         $notice  = $this->translator()->translate('Method not allowed. Must be one of:');
157:         $methods = $this->methods();
158:         $message = '<h1>'.$title."</h1>\n\t\t<p>".$notice.' <strong>'.$methods."</strong></p>\n";
159: 
160:         return $message;
161:     }
162: }
163: