1<?php
2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
3//
4// All Rights Reserved. See copyright.txt for details and a complete list of authors.
5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
6// $Id$
7
8use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
9
10class Services_Broker
11{
12	private $container;
13	private $extensionPackage;
14
15	function __construct($container, $extensionPackage = '')
16	{
17		$this->container = $container;
18		$this->extensionPackage = $extensionPackage;
19	}
20
21	function process($controller, $action, JitFilter $request)
22	{
23		$access = TikiLib::lib('access');
24
25		try {
26			$this->preExecute();
27
28			$output = $this->attemptProcess($controller, $action, $request);
29
30			if (isset($output['FORWARD'])) {
31				$output['FORWARD'] = array_merge(
32					[
33						'controller' => $controller,
34						'action' => $action,
35					],
36					$output['FORWARD']
37				);
38			}
39
40			if ($access->is_serializable_request()) {
41				echo $access->output_serialized($output);
42			} else {
43				TikiLib::events()->trigger('tiki.process.render');
44				echo $this->render($controller, $action, $output, $request);
45			}
46		} catch (Services_Exception_FieldError $e) {
47			if ($request->modal->int() && $access->is_xml_http_request()) {
48				// Special handling for modal dialog requests
49				// Do not send an error code as bootstrap will just blank out
50				// Render the error as a modal
51				$smarty = TikiLib::lib('smarty');
52				$smarty->assign('title', tr('Oops'));
53				$smarty->assign('detail', ['message' => $e->getMessage()]);
54				$smarty->display("extends:internal/modal.tpl|error-ajax.tpl");
55			} else {
56				$access->display_error(null, $e->getMessage(), $e->getCode());
57			}
58		} catch (Exception $e) {
59			if ($request->modal->int() && $access->is_xml_http_request()) {
60				// Special handling for modal dialog requests
61				// Do not send an error code as bootstrap will just blank out
62				// Render the error as a modal
63				$smarty = TikiLib::lib('smarty');
64				$smarty->assign('title', tr('Oops'));
65				$smarty->assign('detail', ['message' => $e->getMessage()]);
66				$smarty->display("extends:internal/modal.tpl|error-ajax.tpl");
67			} else {
68				$access->display_error(null, $e->getMessage(), $e->getCode());
69			}
70		}
71	}
72
73	function internal($controller, $action, $request = [])
74	{
75		if (! $request instanceof JitFilter) {
76			$request = new JitFilter($request);
77		}
78
79		return $this->attemptProcess($controller, $action, $request);
80	}
81
82	function internalRender($controller, $action, $request)
83	{
84		if (! $request instanceof JitFilter) {
85			$request = new JitFilter($request);
86		}
87
88		$output = $this->internal($controller, $action, $request);
89		return $this->render($controller, $action, $output, $request, true);
90	}
91
92	private function attemptProcess($controller, $action, $request)
93	{
94		try {
95			if ($this->extensionPackage) {
96				$handler = $this->container->get("package.controller." . $this->extensionPackage . ".$controller");
97			} else {
98				$handler = $this->container->get("tiki.controller.$controller");
99			}
100
101			$method = 'action_' . $action;
102
103			if (method_exists($handler, $method)) {
104				if (method_exists($handler, 'setUp')) {
105					$handler->setUp();
106				}
107
108				return $handler->$method($request);
109			} else {
110				throw new Services_Exception(tr('Action not found (%0 in %1)', $action, $controller), 404);
111			}
112		} catch (ServiceNotFoundException $e) {
113			throw new Services_Exception(tr('Controller not found (%0)', $controller), 404);
114		}
115	}
116
117	private function preExecute()
118	{
119		$access = TikiLib::lib('access');
120
121		if ($access->is_xml_http_request() && ! $access->is_serializable_request()) {
122			$headerlib = TikiLib::lib('header');
123			$headerlib->clear_js(true); // Only need the partials
124		}
125	}
126
127	private function render($controller, $action, $output, JitFilter $request, $internal = false)
128	{
129		if (isset($output['FORWARD'])) {
130			$url = TikiLib::lib('service')->getUrl($output['FORWARD']);
131			TikiLib::lib('access')->redirect($url);
132		}
133
134		$smarty = TikiLib::lib('smarty');
135
136		$template = "$controller/$action.tpl";
137
138		//if template doesn't exists, simply return the array given from the action
139		//if noTemplate is specified in the query string, it will skip the template
140		if (! $smarty->templateExists($template) || strpos($_SERVER['QUERY_STRING'], '&noTemplate') !== false) {
141			return json_encode($output);
142		}
143
144		$access = TikiLib::lib('access');
145		foreach ($output as $key => $value) {
146			$smarty->assign($key, $value);
147		}
148
149		$layout = null;
150
151		if ($internal) {
152			$layout = "layouts/internal/layout_view.tpl";
153		} elseif ($layout = $request->modal->int() || $access->is_xml_http_request()) {
154			$layout = $request->modal->int()
155				? 'layouts/internal/modal.tpl'
156				: 'layouts/internal/ajax.tpl';
157		}
158
159		if ($layout) {
160			return $smarty->fetch("extends:$layout|$template");
161		} else {
162			return $smarty->fetch($template);
163		}
164	}
165}
166