Merge pull request #2157 from kurund/CRM-13896
[civicrm-core.git] / CRM / Core / Page.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.4 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2013
32 * $Id$
33 *
34 */
35
36 /**
37 * A Page is basically data in a nice pretty format.
38 *
39 * Pages should not have any form actions / elements in them. If they
40 * do, make sure you use CRM_Core_Form and the related structures. You can
41 * embed simple forms in Page and do your own form handling.
42 *
43 */
44 class CRM_Core_Page {
45
46 /**
47 * The name of the page (auto generated from class name)
48 *
49 * @var string
50 * @access protected
51 */
52 protected $_name;
53
54 /**
55 * the title associated with this page
56 *
57 * @var object
58 * @access protected
59 */
60 protected $_title;
61
62 /**
63 * A page can have multiple modes. (i.e. displays
64 * a different set of data based on the input
65 * @var int
66 * @access protected
67 */
68 protected $_mode;
69
70 /**
71 * Is this object being embedded in another object. If
72 * so the display routine needs to not do any work. (The
73 * parent object takes care of the display)
74 *
75 * @var boolean
76 * @access protected
77 */
78 protected $_embedded = FALSE;
79
80 /**
81 * Are we in print mode? if so we need to modify the display
82 * functionality to do a minimal display :)
83 *
84 * @var boolean
85 * @access protected
86 */
87 protected $_print = FALSE;
88
89 /**
90 * cache the smarty template for efficiency reasons
91 *
92 * @var CRM_Core_Smarty
93 * @access protected
94 * @static
95 */
96 static protected $_template;
97
98 /**
99 * cache the session for efficiency reasons
100 *
101 * @var CRM_Core_Session
102 * @access protected
103 * @static
104 */
105 static protected $_session;
106
107 /**
108 * What to return to the client if in ajax mode (snippet=json)
109 *
110 * @var array
111 */
112 public $ajaxResponse = array();
113
114 /**
115 * class constructor
116 *
117 * @param string $title title of the page
118 * @param int $mode mode of the page
119 *
120 * @return CRM_Core_Page
121 */
122 function __construct($title = NULL, $mode = NULL) {
123 $this->_name = CRM_Utils_System::getClassName($this);
124 $this->_title = $title;
125 $this->_mode = $mode;
126
127 // let the constructor initialize this, should happen only once
128 if (!isset(self::$_template)) {
129 self::$_template = CRM_Core_Smarty::singleton();
130 self::$_session = CRM_Core_Session::singleton();
131 }
132
133 // FIXME - why are we messing with 'snippet'? Why not just pass it directly into $this->_print?
134 if (!empty($_REQUEST['snippet'])) {
135 if ($_REQUEST['snippet'] == CRM_Core_Smarty::PRINT_PDF) {
136 $this->_print = CRM_Core_Smarty::PRINT_PDF;
137 }
138 // FIXME - why does this number not match the constant?
139 elseif ($_REQUEST['snippet'] == 5) {
140 $this->_print = CRM_Core_Smarty::PRINT_NOFORM;
141 }
142 // Support 'json' as well as legacy value '6'
143 elseif (in_array($_REQUEST['snippet'], array(CRM_Core_Smarty::PRINT_JSON, 6))) {
144 $this->_print = CRM_Core_Smarty::PRINT_JSON;
145 }
146 else {
147 $this->_print = CRM_Core_Smarty::PRINT_SNIPPET;
148 }
149 }
150
151 // if the request has a reset value, initialize the controller session
152 if (CRM_Utils_Array::value('reset', $_REQUEST)) {
153 $this->reset();
154 }
155 }
156
157 /**
158 * This function takes care of all the things common to all
159 * pages. This typically involves assigning the appropriate
160 * smarty variable :)
161 *
162 * @return string The content generated by running this page
163 */
164 function run() {
165 if ($this->_embedded) {
166 return;
167 }
168
169 self::$_template->assign('mode', $this->_mode);
170
171 $pageTemplateFile = $this->getHookedTemplateFileName();
172 self::$_template->assign('tplFile', $pageTemplateFile);
173
174 // invoke the pagRun hook, CRM-3906
175 CRM_Utils_Hook::pageRun($this);
176
177 if ($this->_print) {
178 if (in_array( $this->_print, array( CRM_Core_Smarty::PRINT_SNIPPET,
179 CRM_Core_Smarty::PRINT_PDF, CRM_Core_Smarty::PRINT_NOFORM, CRM_Core_Smarty::PRINT_JSON ))) {
180 $content = self::$_template->fetch('CRM/common/snippet.tpl');
181 }
182 else {
183 $content = self::$_template->fetch('CRM/common/print.tpl');
184 }
185
186 CRM_Utils_System::appendTPLFile($pageTemplateFile,
187 $content,
188 $this->overrideExtraTemplateFileName()
189 );
190
191 //its time to call the hook.
192 CRM_Utils_Hook::alterContent($content, 'page', $pageTemplateFile, $this);
193
194 if ($this->_print == CRM_Core_Smarty::PRINT_PDF) {
195 CRM_Utils_PDF_Utils::html2pdf($content, "{$this->_name}.pdf", FALSE,
196 array('paper_size' => 'a3', 'orientation' => 'landscape')
197 );
198 }
199 elseif ($this->_print == CRM_Core_Smarty::PRINT_JSON) {
200 $this->ajaxResponse['content'] = $content;
201 CRM_Core_Page_AJAX::returnJsonResponse($this->ajaxResponse);
202 }
203 else {
204 echo $content;
205 }
206 CRM_Utils_System::civiExit();
207 }
208
209 $config = CRM_Core_Config::singleton();
210
211 // TODO: Is there a better way to ensure these actions don't happen during AJAX requests?
212 if (empty($_GET['snippet'])) {
213 // Version check and intermittent alert to admins
214 CRM_Utils_VersionCheck::singleton()->versionAlert();
215
216 // Debug msg once per hour
217 if ($config->debug && CRM_Core_Permission::check('administer CiviCRM') && CRM_Core_Session::singleton()->timer('debug_alert', 3600)) {
218 $msg = ts('Warning: Debug is enabled in <a href="%1">system settings</a>. This should not be enabled on production servers.', array(1 => CRM_Utils_System::url('civicrm/admin/setting/debug', 'reset=1')));
219 CRM_Core_Session::setStatus($msg, ts('Debug Mode'));
220 }
221 }
222
223 $content = self::$_template->fetch('CRM/common/' . strtolower($config->userFramework) . '.tpl');
224
225 // Render page header
226 if (!defined('CIVICRM_UF_HEAD') && $region = CRM_Core_Region::instance('html-header', FALSE)) {
227 CRM_Utils_System::addHTMLHead($region->render(''));
228 }
229 CRM_Utils_System::appendTPLFile($pageTemplateFile, $content);
230
231 //its time to call the hook.
232 CRM_Utils_Hook::alterContent($content, 'page', $pageTemplateFile, $this);
233
234 echo CRM_Utils_System::theme($content, $this->_print);
235 return;
236 }
237
238 /**
239 * Store the variable with the value in the form scope
240 *
241 * @param string|array $name name of the variable or an assoc array of name/value pairs
242 * @param mixed $value value of the variable if string
243 *
244 * @access public
245 *
246 * @return void
247 *
248 */
249 function set($name, $value = NULL) {
250 self::$_session->set($name, $value, $this->_name);
251 }
252
253 /**
254 * Get the variable from the form scope
255 *
256 * @param string name : name of the variable
257 *
258 * @access public
259 *
260 * @return mixed
261 *
262 */
263 function get($name) {
264 return self::$_session->get($name, $this->_name);
265 }
266
267 /**
268 * assign value to name in template
269 *
270 * @param array|string $name name of variable
271 * @param mixed $value value of varaible
272 *
273 * @return void
274 * @access public
275 */
276 function assign($var, $value = NULL) {
277 self::$_template->assign($var, $value);
278 }
279
280 /**
281 * assign value to name in template by reference
282 *
283 * @param array|string $name name of variable
284 * @param mixed $value (reference) value of varaible
285 *
286 * @return void
287 * @access public
288 */
289 function assign_by_ref($var, &$value) {
290 self::$_template->assign_by_ref($var, $value);
291 }
292
293 /**
294 * appends values to template variables
295 *
296 * @param array|string $tpl_var the template variable name(s)
297 * @param mixed $value the value to append
298 * @param bool $merge
299 */
300 function append($tpl_var, $value=NULL, $merge=FALSE) {
301 self::$_template->append($tpl_var, $value, $merge);
302 }
303
304 /**
305 * Returns an array containing template variables
306 *
307 * @param string $name
308 * @param string $type
309 * @return array
310 */
311 function get_template_vars($name=null) {
312 return self::$_template->get_template_vars($name);
313 }
314
315 /**
316 * function to destroy all the session state of this page.
317 *
318 * @access public
319 *
320 * @return void
321 */
322 function reset() {
323 self::$_session->resetScope($this->_name);
324 }
325
326 /**
327 * Use the form name to create the tpl file name
328 *
329 * @return string
330 * @access public
331 */
332 function getTemplateFileName() {
333 return str_replace('_',
334 DIRECTORY_SEPARATOR,
335 CRM_Utils_System::getClassName($this)
336 ) . '.tpl';
337 }
338
339 /**
340 * A wrapper for getTemplateFileName that includes calling the hook to
341 * prevent us from having to copy & paste the logic of calling the hook
342 */
343 function getHookedTemplateFileName() {
344 $pageTemplateFile = $this->getTemplateFileName();
345 CRM_Utils_Hook::alterTemplateFile(get_class($this), $this, 'page', $pageTemplateFile);
346 return $pageTemplateFile;
347 }
348
349 /**
350 * Default extra tpl file basically just replaces .tpl with .extra.tpl
351 * i.e. we dont override
352 *
353 * @return string
354 * @access public
355 */
356 function overrideExtraTemplateFileName() {
357 return NULL;
358 }
359
360 /**
361 * setter for embedded
362 *
363 * @param boolean $embedded
364 *
365 * @return void
366 * @access public
367 */
368 function setEmbedded($embedded) {
369 $this->_embedded = $embedded;
370 }
371
372 /**
373 * getter for embedded
374 *
375 * @return boolean return the embedded value
376 * @access public
377 */
378 function getEmbedded() {
379 return $this->_embedded;
380 }
381
382 /**
383 * setter for print
384 *
385 * @param boolean $print
386 *
387 * @return void
388 * @access public
389 */
390 function setPrint($print) {
391 $this->_print = $print;
392 }
393
394 /**
395 * getter for print
396 *
397 * @return boolean return the print value
398 * @access public
399 */
400 function getPrint() {
401 return $this->_print;
402 }
403
404 static function &getTemplate() {
405 return self::$_template;
406 }
407
408 function getVar($name) {
409 return isset($this->$name) ? $this->$name : NULL;
410 }
411
412 function setVar($name, $value) {
413 $this->$name = $value;
414 }
415 }
416