1: <?php
2:
3: namespace Charcoal\App\Handler;
4:
5:
6: use Psr\Log\LoggerAwareInterface;
7: use Psr\Log\LoggerAwareTrait;
8:
9:
10: use Psr\Http\Message\ResponseInterface;
11: use Psr\Http\Message\ServerRequestInterface;
12: use Psr\Http\Message\UriInterface;
13:
14:
15: use Pimple\Container;
16:
17:
18: use Charcoal\Config\ConfigurableInterface;
19: use Charcoal\Config\ConfigurableTrait;
20:
21:
22: use Charcoal\View\ViewInterface;
23: use Charcoal\View\ViewableInterface;
24: use Charcoal\View\ViewableTrait;
25:
26:
27: use Charcoal\Translator\TranslatorAwareTrait;
28:
29:
30: use Charcoal\App\AppConfig;
31: use Charcoal\App\Template\TemplateInterface;
32: use Charcoal\App\Handler\HandlerInterface;
33: use Charcoal\App\Handler\HandlerConfig;
34:
35: 36: 37: 38: 39: 40: 41: 42:
43: abstract class AbstractHandler implements
44: ConfigurableInterface,
45: HandlerInterface,
46: LoggerAwareInterface,
47: ViewableInterface
48: {
49: use ConfigurableTrait;
50: use LoggerAwareTrait;
51: use TranslatorAwareTrait;
52: use ViewableTrait;
53:
54: 55: 56: 57: 58:
59: protected $container;
60:
61: 62: 63: 64: 65:
66: protected $baseUrl;
67:
68: 69: 70: 71: 72:
73: protected $knownContentTypes = [
74: 'application/json',
75: 'application/xml',
76: 'text/xml',
77: 'text/html',
78: ];
79:
80: 81: 82: 83: 84:
85: public function __construct(Container $container)
86: {
87: $this->setDependencies($container);
88: }
89:
90: 91: 92: 93: 94:
95: public function init()
96: {
97: return $this;
98: }
99:
100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111:
112: public function setDependencies(Container $container)
113: {
114: $this->setLogger($container['logger']);
115: $this->setContainer($container);
116: $this->setBaseUrl($container['base-url']);
117: $this->setView($container['view']);
118: $this->setTranslator($container['translator']);
119:
120: if (isset($container['config']['handlers.defaults'])) {
121: $this->setConfig($container['config']['handlers.defaults']);
122: }
123:
124: return $this;
125: }
126:
127: 128: 129: 130: 131: 132:
133: public function setContainer(Container $container)
134: {
135: $this->container = $container;
136: return $this;
137: }
138:
139: 140: 141: 142: 143: 144: 145:
146: public function createConfig($data = null)
147: {
148: return new HandlerConfig($data);
149: }
150:
151: 152: 153: 154: 155: 156:
157: protected function determineContentType(ServerRequestInterface $request)
158: {
159: $acceptHeader = $request->getHeaderLine('Accept');
160: $selectedContentTypes = array_intersect(explode(',', $acceptHeader), $this->knownContentTypes);
161:
162: if (count($selectedContentTypes)) {
163: return reset($selectedContentTypes);
164: }
165:
166:
167: if (preg_match('/\+(json|xml)/', $acceptHeader, $matches)) {
168: $mediaType = 'application/'.$matches[1];
169: if (in_array($mediaType, $this->knownContentTypes)) {
170: return $mediaType;
171: }
172: }
173:
174: return 'text/html';
175: }
176:
177: 178: 179: 180: 181:
182: protected function renderHtmlOutput()
183: {
184: $config = $this->config();
185: $container = $this->container;
186:
187: $templateIdent = $config['template'];
188:
189: if ($config['cache']) {
190: $cachePool = $container['cache'];
191: $cacheKey = str_replace('/', '.', 'template/'.$templateIdent);
192: $cacheItem = $cachePool->getItem($cacheKey);
193:
194: $output = $cacheItem->get();
195: if ($cacheItem->isMiss()) {
196: $output = $this->renderHtmlTemplate();
197:
198: $cacheItem->set($output, $config['cache_ttl']);
199: }
200: } else {
201: $output = $this->renderHtmlTemplate();
202: }
203:
204: return $output;
205: }
206:
207: 208: 209: 210: 211:
212: public function messageTitle()
213: {
214: return $this->translator()->translate('Application Error');
215: }
216:
217: 218: 219: 220: 221:
222: abstract public function renderHtmlMessage();
223:
224: 225: 226: 227: 228:
229: protected function renderHtmlTemplate()
230: {
231: $config = $this->config();
232: $container = $this->container;
233:
234: $templateIdent = $config['template'];
235: $templateController = $config['controller'];
236: $templateData = $config['template_data'];
237:
238: $templateFactory = $container['template/factory'];
239: if (isset($config['default_controller'])) {
240: $templateFactory->setDefaultClass($config['default_controller']);
241: }
242:
243: if (!$templateController) {
244: return '';
245: }
246:
247: $template = $templateFactory->create($templateController);
248:
249: if (!isset($templateData['error_title'])) {
250: $templateData['error_title'] = $this->messageTitle();
251: }
252:
253: if (!isset($templateData['error_message'])) {
254: $templateData['error_message'] = $this->renderHtmlMessage();
255: }
256:
257: $template->setData($templateData);
258: return $container['view']->render($templateIdent, $template);
259: }
260:
261: 262: 263: 264: 265: 266:
267: public function setBaseUrl($url)
268: {
269: if ($url instanceof UriInterface) {
270: $url = $url->withPath('')->withQuery('')->withFragment('');
271: }
272:
273: $this->baseUrl = $url;
274:
275: return $this;
276: }
277:
278: 279: 280: 281: 282:
283: public function baseUrl()
284: {
285: return $this->baseUrl;
286: }
287: }
288: