|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
class MenuCache extends DataExtension |
|
|
|
|
|
|
4
|
|
|
{ |
|
5
|
|
|
/** |
|
6
|
|
|
* fields are typicall header, menu, footer |
|
7
|
|
|
*/ |
|
8
|
|
|
|
|
9
|
|
|
private static $db = array( |
|
|
|
|
|
|
10
|
|
|
"CachedSection0" => "HTMLText", |
|
11
|
|
|
"CachedSection1" => "HTMLText", |
|
12
|
|
|
"CachedSection2" => "HTMLText", |
|
13
|
|
|
"CachedSection3" => "HTMLText", |
|
14
|
|
|
"CachedSection4" => "HTMLText" |
|
15
|
|
|
); |
|
16
|
|
|
|
|
17
|
|
|
private static $fields = array( |
|
18
|
|
|
0 => "Header", |
|
19
|
|
|
1 => "Menu", |
|
20
|
|
|
2 => "Footer", |
|
21
|
|
|
3 => "LayoutSection", |
|
22
|
|
|
4 => "other", |
|
23
|
|
|
); |
|
24
|
|
|
|
|
25
|
|
|
/* sets the cache number used for getting the "$Layout" of the individual page */ |
|
26
|
|
|
private static $layout_field = 3; |
|
|
|
|
|
|
27
|
|
|
|
|
28
|
|
|
private static $tables_to_clear = array("SiteTree", "SiteTree_Live", "SiteTree_versions"); |
|
|
|
|
|
|
29
|
|
|
|
|
30
|
|
|
public static function field_maker($fieldNumber) |
|
31
|
|
|
{ |
|
32
|
|
|
return "CachedSection".$fieldNumber; |
|
33
|
|
|
} |
|
34
|
|
|
|
|
35
|
|
|
public static function fields_exists($number) |
|
36
|
|
|
{ |
|
37
|
|
|
return (isset(self::$fields[$number])); |
|
38
|
|
|
} |
|
39
|
|
|
|
|
40
|
|
|
public function updateCMSFields(FieldList $fields) |
|
41
|
|
|
{ |
|
42
|
|
|
$fields->addFieldToTab("Root.Caching", new CheckboxField("DoNotCacheMenu", "Do Not Cache Menu")); |
|
43
|
|
|
$fields->addFieldToTab("Root.Caching", new LiteralField("ClearCache", "<a href=\"".$this->owner->Link("clearallfieldcaches")."\">clear cache (do this at the end of all edit sessions)</a>")); |
|
44
|
|
|
return $fields; |
|
45
|
|
|
} |
|
46
|
|
|
|
|
47
|
|
|
//-------------------- menu cache ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ |
|
48
|
|
|
|
|
49
|
|
|
public function clearfieldcache($showoutput = false) |
|
50
|
|
|
{ |
|
51
|
|
|
$fieldsToClear = array(); |
|
52
|
|
|
$fieldsForEach = Config::inst()->get("MenuCache", "fields"); |
|
53
|
|
|
foreach ($fieldsForEach as $key => $field) { |
|
54
|
|
|
$fieldName = self::field_maker($key); |
|
55
|
|
|
$fieldsToClear[] = "\"".$fieldName."\" = ''"; |
|
56
|
|
|
} |
|
57
|
|
|
if (count($fieldsToClear)) { |
|
58
|
|
|
$tablesForEach = Config::inst()->get("MenuCache", "tables_to_clear"); |
|
59
|
|
|
foreach ($tablesForEach as $table) { |
|
|
|
|
|
|
60
|
|
|
$msg = ''; |
|
61
|
|
|
$sql = "UPDATE \"".$table."\" SET ".implode(", ", $fieldsToClear); |
|
62
|
|
|
if (Controller::curr()->getRequest()->param("ID") == "days" && $days = intval(Controller::curr()->getRequest()->param("OtherID"))) { |
|
63
|
|
|
$sql .= ' WHERE \"LastEdited\" > ( NOW() - INTERVAL '.$days.' DAY )'; |
|
64
|
|
|
$msg .= ', created before the last '.$days.' days'; |
|
65
|
|
|
} elseif (Controller::curr()->getRequest()->param("ID") == "thispage") { |
|
66
|
|
|
$sql .= " WHERE \"".$table."\".\"ID\" = ".$this->owner->ID; |
|
67
|
|
|
$msg .= ', for page with ID = '.$this->owner->ID; |
|
68
|
|
|
} |
|
69
|
|
|
if ($showoutput) { |
|
70
|
|
|
DB::alteration_message("Deleting cached data from $table, ".$msg); |
|
71
|
|
|
debug::show($sql); |
|
72
|
|
|
} |
|
73
|
|
|
DB::query($sql); |
|
74
|
|
|
} |
|
75
|
|
|
} |
|
76
|
|
|
return array(); |
|
77
|
|
|
} |
|
78
|
|
|
|
|
79
|
|
|
//add this function to your page class if needed |
|
80
|
|
|
public function onBeforeWrite() |
|
81
|
|
|
{ |
|
82
|
|
|
//$this->clearfieldcache(); // technically this should be done, but it puts a lot of strain on saving so instead we encourage people to use ?flush=1 |
|
|
|
|
|
|
83
|
|
|
parent::onBeforeWrite(); |
|
84
|
|
|
} |
|
85
|
|
|
} |
|
86
|
|
|
|
|
87
|
|
|
class MenuCache_Controller extends Extension |
|
|
|
|
|
|
88
|
|
|
{ |
|
89
|
|
|
private static $allowed_actions = array("showcachedfield","clearfieldcache","showuncachedfield", "clearallfieldcaches"); |
|
|
|
|
|
|
90
|
|
|
|
|
91
|
|
|
protected function getHtml($fieldNumber) |
|
|
|
|
|
|
92
|
|
|
{ |
|
93
|
|
|
$layoutField = Config::inst()->get("MenuCache", "layout_field"); |
|
94
|
|
|
if ($layoutField == $fieldNumber) { |
|
95
|
|
|
$className = $this->owner->ClassName; |
|
96
|
|
|
if ("Page" == $className) { |
|
97
|
|
|
$className = "PageCached"; |
|
98
|
|
|
} |
|
99
|
|
|
return $this->owner->renderWith(array($className, "PageCached")); |
|
100
|
|
|
} else { |
|
101
|
|
|
return $this->owner->renderWith('UsedToCreateCache'.$fieldNumber); |
|
102
|
|
|
} |
|
103
|
|
|
} |
|
104
|
|
|
|
|
105
|
|
|
public function CachedField($fieldNumber) |
|
|
|
|
|
|
106
|
|
|
{ |
|
107
|
|
|
$fieldName = MenuCache::field_maker($fieldNumber); |
|
108
|
|
|
if (isset($_REQUEST["flush"])) { |
|
109
|
|
|
$this->owner->clearfieldcache(); |
|
110
|
|
|
} |
|
111
|
|
|
if (!(MenuCache::fields_exists($fieldNumber))) { |
|
112
|
|
|
user_error("$fieldName is not a field that can be cached", E_USER_ERROR); |
|
113
|
|
|
} else { |
|
114
|
|
|
if (!$this->owner->$fieldName || $this->owner->DoNotCacheMenu) { |
|
115
|
|
|
$fieldID = $fieldNumber; |
|
|
|
|
|
|
116
|
|
|
$content = $this->getHtml($fieldNumber); |
|
117
|
|
|
$sql = "Update \"SiteTree_Live\" Set \"".$fieldName."\" = '".$this->compressAndPrepareHTML($content)."' WHERE \"ID\" = ".$this->owner->ID." LIMIT 1"; |
|
118
|
|
|
DB::query($sql); |
|
119
|
|
|
return $content; |
|
120
|
|
|
} else { |
|
121
|
|
|
return $this->owner->$fieldName; |
|
122
|
|
|
} |
|
123
|
|
|
} |
|
124
|
|
|
} |
|
125
|
|
|
|
|
126
|
|
|
|
|
127
|
|
|
private function compressAndPrepareHTML($html) |
|
128
|
|
|
{ |
|
129
|
|
|
$pat[0] = "/^\s+/"; |
|
|
|
|
|
|
130
|
|
|
$pat[1] = "/\s{2,}/"; |
|
131
|
|
|
$pat[2] = "/\s+\$/"; |
|
132
|
|
|
$rep[0] = ""; |
|
|
|
|
|
|
133
|
|
|
$rep[1] = " "; |
|
134
|
|
|
$rep[2] = ""; |
|
135
|
|
|
$html = preg_replace($pat, $rep, $html); |
|
136
|
|
|
$html = trim($html); |
|
137
|
|
|
return addslashes($html); |
|
138
|
|
|
} |
|
139
|
|
|
|
|
140
|
|
|
|
|
141
|
|
|
|
|
142
|
|
|
public function showcachedfield($httpRequest = null) |
|
|
|
|
|
|
143
|
|
|
{ |
|
144
|
|
|
$fieldNumber = $httpRequest->param("ID"); |
|
145
|
|
|
return $this->getHtml($fieldNumber); |
|
146
|
|
|
} |
|
147
|
|
|
|
|
148
|
|
|
public function showuncachedfield($httpRequest = null) |
|
|
|
|
|
|
149
|
|
|
{ |
|
150
|
|
|
$this->owner->clearfieldcache(); |
|
151
|
|
|
return $this->showcachedfield($httpRequest); |
|
152
|
|
|
} |
|
153
|
|
|
|
|
154
|
|
|
public function clearallfieldcaches($httpRequest = null) |
|
|
|
|
|
|
155
|
|
|
{ |
|
156
|
|
|
$this->owner->clearfieldcache(true); |
|
157
|
|
|
return 'fields have been cleared, <a href="/?flush=all">click to continue...</a>'; |
|
158
|
|
|
} |
|
159
|
|
|
} |
|
160
|
|
|
|
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.