1 <?php
2 /**
3 * @package Joomla.Platform
4 * @subpackage Cache
5 *
6 * @copyright Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 */
9
10 defined('JPATH_PLATFORM') or die;
11
12 /**
13 * Joomla! Cache view type object
14 *
15 * @since 11.1
16 */
17 class JCacheControllerView extends JCacheController
18 {
19 /**
20 * Get the cached view data
21 *
22 * @param object $view The view object to cache output for
23 * @param string $method The method name of the view method to cache output for
24 * @param mixed $id The cache data ID
25 * @param boolean $wrkarounds True to enable workarounds.
26 *
27 * @return boolean True if the cache is hit (false else)
28 *
29 * @since 11.1
30 */
31 public function get($view, $method = 'display', $id = false, $wrkarounds = true)
32 {
33 // If an id is not given generate it from the request
34 if (!$id)
35 {
36 $id = $this->_makeId($view, $method);
37 }
38
39 $data = $this->cache->get($id);
40
41 $locktest = (object) array('locked' => null, 'locklooped' => null);
42
43 if ($data === false)
44 {
45 $locktest = $this->cache->lock($id);
46
47 /*
48 * If the loop is completed and returned true it means the lock has been set.
49 * If looped is true try to get the cached data again; it could exist now.
50 */
51 if ($locktest->locked === true && $locktest->locklooped === true)
52 {
53 $data = $this->cache->get($id);
54 }
55
56 // False means that locking is either turned off or maxtime has been exceeded. Execute the view.
57 }
58
59 if ($data !== false)
60 {
61 if ($locktest->locked === true)
62 {
63 $this->cache->unlock($id);
64 }
65
66 $data = unserialize(trim($data));
67
68 if ($wrkarounds)
69 {
70 echo JCache::getWorkarounds($data);
71 }
72 else
73 {
74 // No workarounds, so all data is stored in one piece
75 echo $data;
76 }
77
78 return true;
79 }
80
81 // No hit so we have to execute the view
82 if (!method_exists($view, $method))
83 {
84 return false;
85 }
86
87 if ($locktest->locked === false && $locktest->locklooped === true)
88 {
89 // We can not store data because another process is in the middle of saving
90 $view->$method();
91
92 return false;
93 }
94
95 // Capture and echo output
96 ob_start();
97 ob_implicit_flush(false);
98 $view->$method();
99 $data = ob_get_clean();
100 echo $data;
101
102 /*
103 * For a view we have a special case. We need to cache not only the output from the view, but the state
104 * of the document head after the view has been rendered. This will allow us to properly cache any attached
105 * scripts or stylesheets or links or any other modifications that the view has made to the document object
106 */
107 if ($wrkarounds)
108 {
109 $data = JCache::setWorkarounds($data);
110 }
111
112 // Store the cache data
113 $this->cache->store(serialize($data), $id);
114
115 if ($locktest->locked === true)
116 {
117 $this->cache->unlock($id);
118 }
119
120 return false;
121 }
122
123 /**
124 * Generate a view cache ID.
125 *
126 * @param object $view The view object to cache output for
127 * @param string $method The method name to cache for the view object
128 *
129 * @return string MD5 Hash
130 *
131 * @since 11.1
132 */
133 protected function _makeId($view, $method)
134 {
135 return md5(serialize(array(JCache::makeId(), get_class($view), $method)));
136 }
137 }
138