...
77 | ```
78 | * **Debug**: If turned on, LiteSpeed Cache will print the LSCache header to LSWS log files.
79 |
80 | CLI commands
81 | -------------
82 |
83 | CLI commands are only allowed to execute from the website host server.
84 |
85 | **Purge All Cache**
86 |
87 | ```
88 | curl -N "http://example.com/lscpurgeall"
89 | ```
90 |
91 | or in `/drupal_root/vendor/bin` folder, execute `drush` command:
92 |
93 | ```
94 | ./drush lscache:purgeall example.com
95 | ```
96 |
97 | **WarmUp whole website**
98 |
99 | ```
100 | curl -N "http://example.com/lscwarmup"
101 | ```
102 |
103 | or in `/drupal_root/vendor/bin` folder, execute `drush` command:
104 |
105 | ```
106 | ./drush lscache:warmup example.com
107 | ```
108 |
109 | CLI `warmup` command can only warm up public page caches. If you want to warm up **Private Cache for Logged In Users**, you need to use the Web GUI warmup in the LSCache admin panel.
110 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "litespeedtech/lscache-drupal",
3 | "description": "Page Cache for LiteSpeed Web Server. Caches pages for any user, handling dynamic content correctly.",
4 | "type": "drupal-module",
5 | "license": "GPL-3.0-only",
6 | "minimum-stability": "dev",
7 | "keywords": ["drupal","cache","litespeed"],
8 | "homepage": "https://www.litespeedtech.com/products/cache-plugins"
9 | }
10 |
--------------------------------------------------------------------------------
/config/install/lite_speed_cache.settings.yml:
--------------------------------------------------------------------------------
1 | lite_speed_cache:
2 | max_age: '64800'
3 | private_max_age: '3600'
4 | cache_status: '1'
5 | private_cache_status: '0'
6 | debug: '0'
7 | esi_blocks: 'id=toolbar-administration'
--------------------------------------------------------------------------------
/config/schema/lite_speed_cache.schema.yml:
--------------------------------------------------------------------------------
1 | lite_speed_cache.settings:
2 | type: config_object
3 | label: 'LiteSpeed Cache settings'
4 | mapping:
5 | lite_speed_cache:
6 | type: mapping
7 | mapping:
8 | esi_on:
9 | type: text
10 | label: 'Turn ESI On or Off.'
11 | max_age:
12 | type: text
13 | label: 'Define max age for public page cache.'
14 | max_age_private:
15 | type: text
16 | lable: 'Define max age for private page cache.'
17 | cache_status:
18 | type: text
19 | label: 'Cache is On or Off'
20 | debug:
21 | type: text
22 | label: 'Weather or not to log debug headers in log files of web server !'
23 | block.settings.lite_speed_cache_block:
24 | type: block_settings
25 | label: 'LSCache block'
26 | mapping:
27 | lite_speed_cache_block_settings:
--------------------------------------------------------------------------------
/images/DrupalPluginEnable.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/litespeedtech/lscache-drupal/8c2df74fcf0fb55e87a38294c2cfa1f94beadf2f/images/DrupalPluginEnable.gif
--------------------------------------------------------------------------------
/images/DrupalPluginInstall.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/litespeedtech/lscache-drupal/8c2df74fcf0fb55e87a38294c2cfa1f94beadf2f/images/DrupalPluginInstall.gif
--------------------------------------------------------------------------------
/lite_speed_cache.info.yml:
--------------------------------------------------------------------------------
1 | name: LiteSpeed Cache
2 | type: module
3 | description: 'Caches pages for any user, handling dynamic content correctly.'
4 | package: Core
5 | configure: lite_speed_cache.form
6 | core_version_requirement: ^8 || ^9 || ^10 || ^11
7 |
--------------------------------------------------------------------------------
/lite_speed_cache.install:
--------------------------------------------------------------------------------
1 | getSchemeAndHttpHost();
27 | $purgeURL = $rootURL . '/lscpurgeall';
28 | LSCacheHelper::curl($purgeURL);
29 | LSCacheHelper::restoreHtaccess();
30 | }
31 |
--------------------------------------------------------------------------------
/lite_speed_cache.links.menu.yml:
--------------------------------------------------------------------------------
1 | lite_speed_cache.admin:
2 | title: 'LSCache Settings'
3 | description: 'Purge all cache or purge by tags!'
4 | route_name: lite_speed_cache.form
5 | parent: 'system.admin_config_development'
6 | weight: 100
--------------------------------------------------------------------------------
/lite_speed_cache.module:
--------------------------------------------------------------------------------
1 | ' . t('About') . '';
21 | $output .= '
' . t('LSCache is used to cache your website on server end, it works similar to reverse proxy but its much more faster as there is no need to use a middleware proxy when everthing is being done by LiteSpeed Web Server. ') . '';
22 |
23 | $output .= '
' . t('Uses') . '
';
24 | $output .= '
';
25 | $output .= '- ' . t('Speeding up your site') . '
';
26 | $output .= '- ' . t('LiteSpeed Cache plugin for Drupal 8 uses same mechanism as their built in plugins to determine if page is cacheable or not. If page is cacheable it is requested from backend and served from LiteSpeed Cache the next time! ') . '
';
27 | $output .= '- ' . t('Caching can be disabled and enabled from configurations page, you do not need to worry about invalidation since our plugin use tags based invalidation.') . '
';
28 | $output .= '
';
29 |
30 | return $output;
31 | }
32 | }
33 |
34 | /**
35 | * Implements hook_user_login().
36 | */
37 | function lite_speed_cache_user_login($account) {
38 | Drupal\lite_speed_cache\Cache\LSCacheHelper::setLoginVary();
39 | }
40 |
41 | /**
42 | * Implements hook_user_logout().
43 | */
44 | function lite_speed_cache_user_logout($account) {
45 | Drupal\lite_speed_cache\Cache\LSCacheHelper::setLogoutVary();
46 | }
47 |
--------------------------------------------------------------------------------
/lite_speed_cache.routing.yml:
--------------------------------------------------------------------------------
1 | lite_speed_cache.form:
2 | path: '/admin/config/development/lscache'
3 | defaults:
4 | _form: 'Drupal\lite_speed_cache\Form\LSCacheForm'
5 | _title: 'LSCache Settings'
6 | requirements:
7 | _permission: 'administer site configuration'
8 |
9 | lite_speed_cache.purgeall:
10 | path: '/lscpurgeall'
11 | defaults:
12 | _controller: '\Drupal\lite_speed_cache\Controller\LSCacheController::purgeAll'
13 | _title: 'LiteSpeedCache: Purge All'
14 | requirements:
15 | _permission: 'access content'
16 | options:
17 | no_cache: 'TRUE'
18 |
19 |
20 | lite_speed_cache.warmup:
21 | path: '/lscwarmup'
22 | defaults:
23 | _controller: '\Drupal\lite_speed_cache\Controller\LSCacheController::warmup'
24 | _title: 'LiteSpeedCache: Warmup'
25 | requirements:
26 | _permission: 'access content'
27 | options:
28 | no_cache: 'TRUE'
29 |
30 |
31 | lite_speed_cache.showesi:
32 | path: '/lscesi'
33 | defaults:
34 | _controller: '\Drupal\lite_speed_cache\Controller\LSCacheController::showesi'
35 | _title: 'LiteSpeedCache: ESI Block'
36 | requirements:
37 | _permission: 'access content'
38 | options:
39 | no_cache: 'TRUE'
40 |
41 |
--------------------------------------------------------------------------------
/lite_speed_cache.services.yml:
--------------------------------------------------------------------------------
1 | services:
2 |
3 | http_response_headers:
4 | class: '\Drupal\lite_speed_cache\EventSubscriber\LSCacheSubscriber'
5 | tags:
6 | - { name: 'event_subscriber' }
7 |
8 |
9 | lsc_commands:
10 | class: \Drupal\lite_speed_cache\Commands\LSCacheCommand
11 | tags:
12 | - { name: drush.command }
13 | arguments: ['@entity_type.manager', '@logger.factory']
--------------------------------------------------------------------------------
/src/Cache/LSCacheBackend.php:
--------------------------------------------------------------------------------
1 |
9 | * @copyright Copyright (c) 2017-2018 LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
10 | * @license https://opensource.org/licenses/GPL-3.0
11 | */
12 | namespace Drupal\lite_speed_cache\Cache;
13 | use Drupal\Core\Cache\CacheBackendInterface;
14 | use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
15 |
16 | class LSCacheBackend extends LSCacheCore implements CacheBackendInterface, CacheTagsInvalidatorInterface {
17 | const PURGE_HEAD_NAME = 'X-LiteSpeed-Purge';
18 | static $publicPurgeTags = [];
19 | static $publicPurgeAll = false;
20 |
21 | /**
22 | * {@inheritdoc}
23 | */
24 | public function get($cid, $allow_invalid = FALSE) {
25 | return FALSE;
26 | }
27 |
28 | /**
29 | * {@inheritdoc}
30 | */
31 | public function getMultiple(&$cids, $allow_invalid = FALSE) {
32 | return [];
33 | }
34 |
35 | /**
36 | * {@inheritdoc}
37 | */
38 | public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = []) {
39 |
40 | $current_path = \Drupal::service('path.current')->getPath();
41 | if(str_starts_with($current_path,'/user/')){
42 | return;
43 | }
44 |
45 | $config = \Drupal::config('lite_speed_cache.settings');
46 | $cacheStatus = $config->get('lite_speed_cache.cache_status');
47 | if($cacheStatus=='0' or $cacheStatus == 'Off') {
48 | return;
49 | }
50 |
51 | if($expire>0){
52 | $this->public_cache_timeout = $expire;
53 | } else {
54 | $this->public_cache_timeout = $config->get('lite_speed_cache.max_age');
55 | }
56 |
57 | $tags = array_unique($tags);
58 | //$tags[] = $cid;
59 | $ftags = $this->filterTags($tags);
60 | $this->cachePublic($ftags);
61 | $this->logDebug($config);
62 | }
63 |
64 |
65 | /**
66 | * {@inheritdoc}
67 | */
68 | public function setMultiple(array $items = []) {
69 | $cacheStatus = $config->get('lite_speed_cache.cache_status');
70 | if($cacheStatus=='0' or $cacheStatus == 'Off') {
71 | return;
72 | }
73 | $this->public_cache_timeout = $config->get('lite_speed_cache.max_age');
74 | $tags = array();
75 | foreach ($items as $cid => $item) {
76 | //$tags[] = $cid;
77 | if($item['tags']){
78 | $tags = array_merge($tags, $item['tags']);
79 | }
80 | }
81 | $ftags = $this->filterTags($tags);
82 | $this->cachePublic($ftags);
83 | $this->logDebug($config);
84 | }
85 |
86 | /**
87 | * send purge header to response object
88 | */
89 | public function purgeAction(){
90 | if(self::$publicPurgeAll){
91 | $tag = 'public, ' . $this->site_only_tag;
92 | $this->purgePublic([$this->site_only_tag]);
93 | $this->logDebug();
94 | return $tag;
95 | } else if (!empty(self::$publicPurgeTags)) {
96 | $tags = $this->filterTags(self::$publicPurgeTags);
97 | if(empty($tags)){
98 | return false;
99 | }
100 | $tag = 'public, ' . $this->tagCommand('', $tags);
101 | $this->purgePublic($tags);
102 | $this->logDebug();
103 | self::$publicPurgeTags=[];
104 | return $tag;
105 | } else {
106 | return false;
107 | }
108 | }
109 |
110 |
111 | /**
112 | * remove general configuration tags, for those change, use purge all cache
113 | */
114 | public function filterTags($tags){
115 | $finalTags = [];
116 | foreach ($tags as $val) {
117 | if ((strpos($val, 'config:') !== False) or (strpos($val, 'user:') !== False) or (strpos($val, 'taxonomy_term') !== False) or (strpos($val, '_view') !== False) or (strpos($val, '_list') !== False) or ($val == "http_response") or ($val == "rendered")) {
118 | continue;
119 | }
120 | else{
121 | $finalTags[]=$val;
122 | }
123 | }
124 | return $finalTags;
125 | }
126 |
127 |
128 | /**
129 | * if enabled debug, write cache header to web server Log file.
130 | */
131 | protected function logDebug($config=false) {
132 | if(!$config){
133 | $config = \Drupal::config('lite_speed_cache.settings');
134 | }
135 | $debug = $config->get('lite_speed_cache.debug');
136 | if($debug=='1' or $debug == 'On') {
137 | error_log($this->getLogBuffer());
138 | }
139 | }
140 |
141 | /**
142 | * {@inheritdoc}
143 | */
144 | public function delete($cid) {
145 | self::$publicPurgeTags[]=$cid;
146 | $this->logDebug();
147 | }
148 |
149 | /**
150 | * {@inheritdoc}
151 | */
152 | public function deleteMultiple(array $cids) {
153 | $items = array_flip($cids);
154 | $tags = array();
155 | foreach ($items as $cid => $item) {
156 | $tags[] = $cid;
157 | }
158 | $this->purgePublic($tags);
159 | $this->logDebug();
160 | }
161 |
162 | /**
163 | * {@inheritdoc}
164 | */
165 | public function deleteAll() {
166 | self::$publicPurgeAll = true;
167 | }
168 |
169 | /**
170 | * {@inheritdoc}
171 | */
172 | public function invalidate($cid) {
173 | $this->delete($cid);
174 | }
175 |
176 | /**
177 | * {@inheritdoc}
178 | */
179 | public function invalidateMultiple(array $cids) {
180 | $this->deleteMultiple($cids);
181 | }
182 |
183 | /**
184 | * {@inheritdoc}
185 | */
186 | public function invalidateTags(array $tags) {
187 | $this->tagsForSite(self::$publicPurgeTags, $tags);
188 | }
189 |
190 | /**
191 | * {@inheritdoc}
192 | */
193 | public function invalidateAll() {
194 | self::$publicPurgeAll = true;
195 |
196 | }
197 |
198 | /**
199 | * {@inheritdoc}
200 | */
201 | public function garbageCollection() {
202 | }
203 |
204 | /**
205 | * {@inheritdoc}
206 | */
207 | public function removeBin() {
208 | self::$publicPurgeAll = true;
209 | }
210 |
211 |
212 | }
213 |
--------------------------------------------------------------------------------
/src/Cache/LSCacheBackendFactory.php:
--------------------------------------------------------------------------------
1 |
9 | * @copyright Copyright (c) 2017-2018 LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
10 | * @license https://opensource.org/licenses/GPL-3.0
11 | */
12 | namespace Drupal\lite_speed_cache\Cache;
13 | use Drupal\Core\Cache\CacheFactory;
14 |
15 |
16 | class LSCacheBackendFactory extends CacheFactory {
17 |
18 | protected $bins = [];
19 |
20 | /**
21 | * {@inheritdoc}
22 | */
23 | public function get($bin) {
24 |
25 | if($bin!=='page'){
26 | return parent::get($bin);
27 | }
28 |
29 | if (isset($this->bins[$bin])) {
30 | return $this->bins[$bin];
31 | }
32 |
33 | $this->bins[$bin] = new LSCacheBackend();
34 | return $this->bins[$bin];
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/Cache/LSCacheBase.php:
--------------------------------------------------------------------------------
1 |
9 | * @copyright Copyright (c) 2017-2018 LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
10 | * @license https://opensource.org/licenses/GPL-3.0
11 | */
12 |
13 |
14 | namespace Drupal\lite_speed_cache\Cache;
15 |
16 | class LSCacheBase
17 | {
18 | const PUBLIC_CACHE_CONTROL = 'X-LiteSpeed-Cache-Control:public,max-age=';
19 | const PRIVATE_CACHE_CONTROL = 'X-LiteSpeed-Cache-Control:private,max-age=';
20 | const CACHE_PURGE = 'X-LiteSpeed-Purge:';
21 | const CACHE_TAG = 'X-LiteSpeed-Tag:';
22 | const VARY_COOKIE = '_lscache_vary';
23 | const PRIVATE_COOKIE = 'lsc_private';
24 |
25 | protected $public_cache_timeout = '1000000';
26 | protected $private_cache_timeout = '5000';
27 | protected $logbuffer = "";
28 |
29 | /**
30 | *
31 | * load class configuration from $config object
32 | *
33 | * @since 1.0.0
34 | */
35 | public function config($config)
36 | {
37 | $this->public_cache_timeout = $config['public_cache_timeout'];
38 | $this->private_cache_timeout = $config['private_cache_timeout'];
39 | }
40 |
41 | /**
42 | *
43 | * put tag into Array in the format for this site only.
44 | *
45 | * @since 1.0.0
46 | */
47 | protected function tagsForSite(Array &$tagArray, $rawTags, $prefix = "")
48 | {
49 | if (!isset($rawTags)) {
50 | return;
51 | }
52 |
53 | if ($rawTags == "") {
54 | return;
55 | }
56 |
57 | if(is_array($rawTags)){
58 | $tags = $rawTags;
59 | } else {
60 | $tags = explode(",", $rawTags);
61 | }
62 |
63 | foreach ($tags as $tag) {
64 | if(trim($tag)==""){
65 | continue;
66 | }
67 |
68 | $tagStr = $prefix . trim($tag);
69 | if(!in_array($tagStr, $tagArray, false)){
70 | array_push($tagArray, $tagStr);
71 | }
72 | }
73 | }
74 |
75 | /**
76 | *
77 | * put tag in Array together to make an head command .
78 | *
79 | * @since 1.0.0
80 | */
81 | protected function tagCommand($start, Array $tagArray){
82 | $cmd = $start;
83 |
84 | foreach ($tagArray as $tag) {
85 | $cmd .= $tag . ",";
86 | }
87 | return substr($cmd,0,-1);
88 | }
89 |
90 | /**
91 | *
92 | * purge public cache with specified tags for this site.
93 | *
94 | * @since 1.0.0
95 | */
96 | public function purgePublic($publicTags)
97 | {
98 | if ((!isset($publicTags)) || ($publicTags == "")) {
99 | return;
100 | }
101 |
102 | $siteTags = Array();
103 | $this->tagsForSite($siteTags, $publicTags);
104 | $LSheader = $this->tagCommand(self::CACHE_PURGE . 'public,' , $siteTags) ;
105 | $this->liteSpeedHeader($LSheader);
106 | }
107 |
108 | /**
109 | *
110 | * purge private cache with specified tags for this site.
111 | *
112 | * @since 1.0.0
113 | */
114 | public function purgePrivate($privateTags)
115 | {
116 | if ((!isset($privateTags)) || ($privateTags == "")) {
117 | return;
118 | }
119 |
120 | $siteTags = Array();
121 | $this->tagsForSite($siteTags, $privateTags);
122 | $LSheader = $this->tagCommand( self::CACHE_PURGE . 'private,' , $siteTags);
123 | $this->liteSpeedHeader($LSheader);
124 | }
125 |
126 | /**
127 | *
128 | * purge all public cache of this site
129 | *
130 | * @since 1.0.0
131 | */
132 | public function purgeAllPublic()
133 | {
134 | $LSheader = self::CACHE_PURGE . 'public,*';
135 | $this->liteSpeedHeader($LSheader);
136 | }
137 |
138 | /**
139 | *
140 | * purge all private cache of this session
141 | *
142 | * @since 0.1
143 | */
144 | public function purgeAllPrivate()
145 | {
146 | $LSheader = self::CACHE_PURGE . 'private,*';
147 | $this->liteSpeedHeader($LSheader);
148 | }
149 |
150 | /**
151 | *
152 | * Cache this page for public use if not cached before
153 | *
154 | * @since 1.0.0
155 | * @param string $publicTags
156 | */
157 | public function cachePublic($publicTags, $esi=false)
158 | {
159 | if (!isset($publicTags) || ($publicTags == null)) {
160 | return;
161 | }
162 |
163 | $LSheader = self::PUBLIC_CACHE_CONTROL . $this->public_cache_timeout;
164 | if($esi){
165 | $LSheader .= ',esi=on';
166 | }
167 |
168 | $this->liteSpeedHeader($LSheader);
169 |
170 | $siteTags = Array();
171 | $this->tagsForSite($siteTags, $publicTags);
172 |
173 | $LSheader = $this->tagCommand( self::CACHE_TAG , $siteTags);
174 | $this->liteSpeedHeader($LSheader);
175 | }
176 |
177 | /**
178 | *
179 | * Cache this page for private session if not cached before
180 | *
181 | * @since 0.1
182 | */
183 | public function cachePrivate($privateTags = "", $esi = false)
184 | {
185 | if ( !isset($privateTags) || ($privateTags == "") ) {
186 | if ( !isset($publicTags) || ($publicTags == "")) {
187 | return;
188 | }
189 | }
190 |
191 | $LSheader = self::PRIVATE_CACHE_CONTROL . $this->private_cache_timeout;
192 | if($esi){
193 | $LSheader .= ',esi=on';
194 | }
195 | $this->liteSpeedHeader($LSheader);
196 |
197 | $siteTags = Array();
198 | if($privateTags!=""){
199 | $this->tagsForSite($siteTags, $privateTags);
200 | }
201 | else{
202 | array_push($siteTags, 'pvt');
203 | }
204 |
205 | $LSheader = $this->tagCommand( self::CACHE_TAG , $siteTags);
206 | $this->liteSpeedHeader($LSheader);
207 | }
208 |
209 | /**
210 | *
211 | * Cache this page for private use if not cached before
212 | *
213 | * @since 1.0.0
214 | */
215 | protected function liteSpeedHeader($LSheader)
216 | {
217 | $this->logbuffer .= $LSheader . " ";
218 | header($LSheader);
219 | }
220 |
221 | /**
222 | *
223 | * set or delete private cookie.
224 | *
225 | * @since 1.0.0
226 | */
227 | public function checkPrivateCookie($path = '/')
228 | {
229 | if (!isset($_COOKIE[self::PRIVATE_COOKIE])) {
230 | setcookie(self::PRIVATE_COOKIE, md5((String)rand()), 0, $path);
231 | }
232 | }
233 |
234 | /**
235 | *
236 | * set or delete cache vary cookie, if cookie need no change return true;
237 | *
238 | * @since 1.0.0
239 | */
240 | public function checkVary($value, $path='/')
241 | {
242 | if ($value == "") {
243 | if (isset($_COOKIE[self::VARY_COOKIE])) {
244 | setcookie(self::VARY_COOKIE, "", '0', $path);
245 | return false;
246 | }
247 | return true;
248 | }
249 |
250 | if(!isset($_COOKIE[self::VARY_COOKIE])){
251 | setcookie(self::VARY_COOKIE, $value, '0', $path);
252 | return false;
253 | }
254 |
255 | if($_COOKIE[self::VARY_COOKIE] != $value){
256 | setcookie(self::VARY_COOKIE, $value, '0', $path);
257 | return false;
258 | }
259 |
260 | return true;
261 | }
262 |
263 | /**
264 | *
265 | * get LiteSpeedCache special head log
266 | *
267 | * @since 1.0.0
268 | */
269 | public function getLogBuffer()
270 | {
271 | $retVal = $this->logbuffer;
272 | $this->logbuffer = '';
273 | return $retVal;
274 | }
275 |
276 |
277 |
278 | public function getSeverType() {
279 |
280 | if (isset($_SERVER['HTTP_X_LSCACHE']) && $_SERVER['HTTP_X_LSCACHE']) {
281 | return 'LITESPEED_SERVER_ADC';
282 | } elseif (isset($_SERVER['LSWS_EDITION']) && ( strpos($_SERVER['LSWS_EDITION'], 'Openlitespeed') !== FALSE )) {
283 | return 'LITESPEED_SERVER_OLS';
284 | } elseif (isset($_SERVER['SERVER_SOFTWARE']) && $_SERVER['SERVER_SOFTWARE'] == 'LiteSpeed') {
285 | return 'LITESPEED_SERVER_ENT';
286 | } else {
287 | return false;
288 | }
289 |
290 | }
291 |
292 | }
--------------------------------------------------------------------------------
/src/Cache/LSCacheCore.php:
--------------------------------------------------------------------------------
1 |
9 | * @copyright Copyright (c) 2017-2018 LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
10 | * @license https://opensource.org/licenses/GPL-3.0
11 | */
12 | namespace Drupal\lite_speed_cache\Cache;
13 |
14 | class LSCacheCore extends LSCacheBase
15 | {
16 | private static $instance = null;
17 |
18 | protected $site_only_tag = "";
19 |
20 | protected $loginCachable = false;
21 |
22 | /**
23 | *
24 | * set the specified tag for this site
25 | *
26 | * @since 1.0.0
27 | */
28 | public function __construct($tag = '')
29 | {
30 | if(!isset($tag) || ($tag=='')){
31 | $this->site_only_tag = substr(md5(__DIR__),0,4);
32 | }
33 | else{
34 | $this->site_only_tag = $tag;
35 | }
36 | }
37 |
38 | /**
39 | *
40 | * purge all public cache of this site
41 | *
42 | * @since 1.0.0
43 | */
44 | public function purgeAllPublic()
45 | {
46 | $LSheader = self::CACHE_PURGE . 'public,' . $this->site_only_tag;
47 | $this->liteSpeedHeader($LSheader);
48 | }
49 |
50 | /**
51 | *
52 | * purge all private cache of this session
53 | *
54 | * @since 0.1
55 | */
56 | public function purgeAllPrivate()
57 | {
58 | $LSheader = self::CACHE_PURGE . 'private,' . $this->site_only_tag;
59 | $this->liteSpeedHeader($LSheader);
60 | }
61 |
62 | /**
63 | *
64 | * Cache this page for public use if not cached before
65 | *
66 | * @since 1.0.1
67 | */
68 | public function cachePublic($publicTags, $esi=false)
69 | {
70 | if (!isset($publicTags) || ($publicTags == null)) {
71 | return;
72 | }
73 |
74 | $LSheader = self::PUBLIC_CACHE_CONTROL . $this->public_cache_timeout;
75 | if($esi){
76 | $LSheader .= ',esi=on';
77 | }
78 | $this->liteSpeedHeader($LSheader);
79 |
80 | $siteTags = Array();
81 | array_push($siteTags, '');
82 | $this->tagsForSite($siteTags, $publicTags);
83 |
84 | $LSheader = $this->tagCommand( self::CACHE_TAG , $siteTags);
85 | $this->liteSpeedHeader($LSheader);
86 | }
87 |
88 |
89 | /**
90 | *
91 | * put tag in Array together to make an head command .
92 | *
93 | * @since 1.0.0
94 | */
95 | public function tagCommand($start, Array $tagArray){
96 | $cmd = $start;
97 |
98 | foreach ($tagArray as $tag) {
99 | $cmd .= $this->site_only_tag . $tag . ",";
100 | }
101 | return substr($cmd,0,-1);
102 | }
103 |
104 |
105 | /**
106 | *
107 | * Cache this page for private session if not cached before
108 | *
109 | * @since 0.1
110 | */
111 | public function cachePrivate($privateTags = "", $esi=false)
112 | {
113 | if ( !isset($privateTags) || ($privateTags == "") ) {
114 | return;
115 | }
116 |
117 | $LSheader = self::PRIVATE_CACHE_CONTROL . $this->private_cache_timeout;
118 | if($esi){
119 | $LSheader .= ',esi=on';
120 | }
121 | $this->liteSpeedHeader($LSheader);
122 |
123 | $siteTags = Array();
124 | $this->tagsForSite($siteTags, $privateTags);
125 | array_push($siteTags, '');
126 |
127 | $LSheader = $this->tagCommand( self::CACHE_TAG , $siteTags);
128 | $this->liteSpeedHeader($LSheader);
129 | }
130 |
131 | public function getSiteOnlyTag(){
132 | return $this->site_only_tag;
133 | }
134 |
135 |
136 | public static function getInstance()
137 | {
138 | if (self::$instance == null)
139 | {
140 | self::$instance = new LSCacheCore();
141 | }
142 |
143 | return self::$instance;
144 | }
145 |
146 | public function setLoginCachable($loginCachable){
147 | if($loginCachable == '0'){
148 | $this->loginCachable = false;
149 | } else {
150 | $this->loginCachable = true;
151 | }
152 | }
153 |
154 | public function getLoginCachable(){
155 | return $this->loginCachable;
156 | }
157 |
158 |
159 | /**
160 | *
161 | * purge public cache with specified tags for this site.
162 | *
163 | * @since 1.0.0
164 | */
165 | public function purgePublic($publicTags)
166 | {
167 | if ((!isset($publicTags)) || ($publicTags == "")) {
168 | return;
169 | }
170 |
171 | $siteTags = Array();
172 | $this->tagsForSite($siteTags, $publicTags, $this->site_only_tag);
173 | $LSheader = $this->tagCommand(self::CACHE_PURGE . 'public,' , $siteTags) ;
174 | $this->liteSpeedHeader($LSheader);
175 | }
176 |
177 |
178 | /**
179 | *
180 | * purge private cache with specified tags for this site.
181 | *
182 | * @since 1.0.0
183 | */
184 | public function purgePrivate($privateTags)
185 | {
186 | if ((!isset($privateTags)) || ($privateTags == "")) {
187 | return;
188 | }
189 |
190 | $siteTags = Array();
191 | $this->tagsForSite($siteTags, $privateTags, $this->site_only_tag);
192 | $LSheader = $this->tagCommand( self::CACHE_PURGE . 'private,' , $siteTags);
193 | $this->liteSpeedHeader($LSheader);
194 | }
195 |
196 |
197 | }
--------------------------------------------------------------------------------
/src/Cache/LSCacheHelper.php:
--------------------------------------------------------------------------------
1 | ' . PHP_EOL;
13 | $directives .= ' CacheLookup on' . PHP_EOL;
14 | $directives .= ' php_value output_buffering Off' . PHP_EOL;
15 | $directives .= '' . PHP_EOL;
16 | $directives .= '### LITESPEED_CACHE_END';
17 |
18 | $pattern = '@### LITESPEED_CACHE_START - Do not remove this line.*?### LITESPEED_CACHE_END@s';
19 |
20 | if (file_exists($htaccess)) {
21 | $content = file_get_contents($htaccess);
22 | $newContent = preg_replace($pattern, $directives, $content, -1, $count);
23 |
24 | if ($count <= 0) {
25 | $newContent = preg_replace('@\
.*?\<\/IfModule\>@s', '', $content);
26 | $newContent = preg_replace('@CacheLookup\ on@s', '', $newContent);
27 | file_put_contents($htaccess, $directives .PHP_EOL .$newContent);
28 | }
29 | } else {
30 | file_put_contents($htaccess, $directives);
31 | }
32 | }
33 |
34 | public static function restoreHtaccess(){
35 | $htaccess = DRUPAL_ROOT . '/.htaccess';
36 |
37 | $pattern = '@### LITESPEED_CACHE_START - Do not remove this line.*?### LITESPEED_CACHE_END@s';
38 |
39 | if (file_exists($htaccess)) {
40 | $content = file_get_contents($htaccess);
41 | $newContent = preg_replace($pattern, '', $content, -1, $count);
42 |
43 | if ($count <= 0) {
44 | $newContent = preg_replace('@\.*?\<\/IfModule\>@s', '', $content);
45 | $newContent = preg_replace('@CacheLookup\ on@s', '', $newContent);
46 | file_put_contents($htaccess, $newContent);
47 | } else {
48 | file_put_contents($htaccess, $newContent);
49 | }
50 | }
51 |
52 | }
53 |
54 | public static function initConfigs(){
55 | // Prevent gzip cause broken website layout
56 | $config = \Drupal::service('config.factory')->getEditable('system.performance');
57 | $config->set('css.preprocess', '0');
58 | $config->set('js.preprocess', '0');
59 | $config->set('css.gzip', '0');
60 | $config->set('js.gzip', '0');
61 | $config->save();
62 | }
63 |
64 | public static function setLoginVary(){
65 | $lscInstance = new LSCacheCore();
66 | $lscInstance->checkVary("user:loggedin");
67 | $lscInstance->checkPrivateCookie();
68 | }
69 |
70 | public static function setLogoutVary(){
71 | $lscInstance = new LSCacheCore();
72 | $lscInstance->checkVary("");
73 | }
74 |
75 | public static function getSiteUrls($rootUrl){
76 | $database = \Drupal::database();
77 | $query = $database->select('path_alias', 'base_table');
78 | $query->condition('base_table.status', 1);
79 | $query->fields('base_table', ['alias','langcode']);
80 | $result = $query->execute()->fetchAllKeyed();
81 |
82 | $siteUrls = [$rootUrl];
83 | foreach($result as $alias => $langcode){
84 | $siteUrls[]= $rootUrl . $alias;
85 | $siteUrls[]= $rootUrl .'/' . $langcode. $alias;
86 | }
87 |
88 | $query1 = $database->select('node');
89 | $query1->fields('node', ['nid','langcode']);
90 | $result = $query1->execute()->fetchAllKeyed();
91 | $pm = \Drupal::service('path_alias.manager');
92 | foreach($result as $nid => $langcode){
93 | $path_alias = $pm->getAliasByPath('/node/'.$nid, $langcode);
94 | $siteUrls[]= $rootUrl . $path_alias;
95 | $siteUrls[]= $rootUrl .'/' . $langcode. $path_alias;
96 | }
97 |
98 | $array1 = array_unique($siteUrls);
99 | return $array1;
100 | }
101 |
102 |
103 | public static function curl($url) {
104 | $ch = curl_init();
105 |
106 | curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
107 | curl_setopt($ch, CURLOPT_HEADER, 0);
108 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
109 | curl_setopt($ch, CURLOPT_URL, $url);
110 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
111 | curl_setopt($ch, CURLOPT_FAILONERROR, 0);
112 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
113 | curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0');
114 |
115 | $data = curl_exec($ch);
116 | $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
117 | curl_close($ch);
118 |
119 | if(!empty($data)) return $data;
120 | return $httpcode;
121 |
122 | }
123 | }
--------------------------------------------------------------------------------
/src/Commands/LSCacheCommand.php:
--------------------------------------------------------------------------------
1 | output()->writeln('need parameter @rootURL, eg: http://example.com');
23 | }
24 |
25 | $url = $rootURL .'/lscpurgeall';
26 | $result = LSCacheHelper::curl($url);
27 |
28 | if(!is_numeric($result)){
29 | $this->output()->writeln($result);
30 | } else if($result=='200'){
31 | $this->output()->writeln('Purge All Cache Successfull!');
32 | } else {
33 | $this->output()->writeln('Purge All Cache Failed!');
34 | }
35 |
36 | }
37 |
38 | /**
39 | * Warmup whole site LiteSpeed Cache
40 | *
41 | * @command lscache:warmup
42 | * @alias lscache-warmup
43 | * @param $rootURL Domain or root URL of website, eg: http://example.com
44 | */
45 | public function WarmUpCommand($rootURL = '') {
46 | if(empty($rootURL)) {
47 | return $this->output()->writeln('need parameter @rootURL, eg: http://example.com');
48 | }
49 |
50 | $siteUrls = LSCacheHelper::getSiteUrls($rootURL);
51 |
52 | if(empty($siteUrls)){
53 | return $this->output()->writeln('No WarmUp Urls found');
54 | }
55 |
56 | $this->crawlUrls($siteUrls);
57 |
58 | }
59 |
60 |
61 | private function crawlUrls($urls) {
62 | set_time_limit(0);
63 | $acceptCode = array(200, 201);
64 | $total = count($urls);
65 | $current = 0;
66 |
67 | foreach ($urls as $url) {
68 | $current++;
69 | $ch = curl_init();
70 | curl_setopt($ch, CURLOPT_URL, $url);
71 | curl_setopt($ch, CURLOPT_HEADER, false);
72 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
73 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
74 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
75 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
76 | curl_setopt($ch, CURLOPT_MAXREDIRS, 1);
77 | curl_setopt($ch, CURLOPT_USERAGENT, 'lscache_runner');
78 | curl_setopt($ch, CURLOPT_ENCODING, "gzip");
79 | curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
80 |
81 | $buffer = curl_exec($ch);
82 | $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
83 | curl_close($ch);
84 |
85 | if (in_array($httpcode, $acceptCode)) {
86 | $this->output->writeln($current . '/'. $total . ' Warm up: ' . $url . " success!");
87 | } else if($httpcode==428){
88 | $this->output->writeln("Web Server crawler feature not enabled, please check https://www.litespeedtech.com/support/wiki/doku.php/litespeed_wiki:cache:lscwp:configuration:enabling_the_crawler");
89 | break;
90 | } else {
91 | $this->output->writeln($current . '/'. $total . ' Warm up: ' . $url . " failed!");
92 | }
93 | }
94 | }
95 | }
--------------------------------------------------------------------------------
/src/Controller/LSCacheController.php:
--------------------------------------------------------------------------------
1 | purgeAllPublic();
22 | $result = 'All LiteSpeed Cache purged!' . PHP_EOL;
23 |
24 | } else {
25 | $result = 'Access denied!
please access from localhost with "curl " command!
' . PHP_EOL;
26 | }
27 |
28 | return new HtmlResponse(['#markup'=>$result]);
29 |
30 | }
31 |
32 | public function warmup(Request $request) {
33 | $rootURL = $request->getSchemeAndHttpHost();
34 | $siteUrls = LSCacheHelper::getSiteUrls($rootURL);
35 | $lscUrl = $rootURL . '/admin/config/development/lscache';
36 |
37 | $visitorIP = $_SERVER['REMOTE_ADDR'];
38 | $serverIP = $_SERVER['SERVER_ADDR'];
39 |
40 | if(\Drupal::currentUser() && \Drupal::currentUser()->isAuthenticated()) {
41 | set_time_limit(0);
42 | ob_implicit_flush(TRUE);
43 | if (ob_get_contents()) {
44 | ob_end_clean();
45 | }
46 |
47 | echo 'LSCache Warmup Start...
' . PHP_EOL;
48 | echo 'Warmup Public Caches...
' . PHP_EOL;
49 | $this->crawlUrls($siteUrls,false);
50 |
51 | $config = \Drupal::config('lite_speed_cache.settings');
52 | $cacheStatus = $config->get('lite_speed_cache.private_cache_status');
53 | if($cacheStatus=='1') {
54 | $sessionName='';
55 | $sc = new SessionConfiguration();
56 | if($sc->hasSession($request)){
57 | $options = $sc->getOptions($request);
58 | $sessionName = $options['name'];
59 | }
60 | $sessionValue = $request->cookies->get($sessionName);
61 | $cookie = 'lsc_private=e70f67d087a65a305e80267ba3bfbc97;_lscache_vary=user%3Aloggedin;' . $sessionName . '=' . $sessionValue;
62 | echo '
Warmup Private Cache for logged-in users...
' . PHP_EOL;
63 | $this->crawlUrls($siteUrls,false,$cookie);
64 | }
65 | usleep(3000000);
66 | \Drupal::messenger()->addMessage(t('Instructed LiteSpeed Web Server to warmup this site cache!'));
67 | echo '';
70 | }
71 | else if(($visitorIP=="127.0.0.1") || ($serverIP=="127.0.0.1") || ($visitorIP==$serverIP)){
72 | $this->crawlUrls($siteUrls, true);
73 | } else {
74 | return new HtmlResponse( ['#markup'=>'please access from localhost with "curl " command!']);
75 | }
76 |
77 | return new HtmlResponse(['#markup'=>'']);
78 |
79 | }
80 |
81 |
82 | public function showesi() {
83 | return [
84 | 'content' => [
85 | '#markup' => 'LiteSpeed ESI Cache.',
86 | ],
87 | ] ;
88 | }
89 |
90 | private function crawlUrls($urls, $cli=false, $cookie='') {
91 | $acceptCode = array(200, 201);
92 | $total = count($urls);
93 | $current = 0;
94 |
95 | foreach ($urls as $url) {
96 | $current++;
97 | $ch = curl_init();
98 | curl_setopt($ch, CURLOPT_URL, $url);
99 | curl_setopt($ch, CURLOPT_HEADER, false);
100 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
101 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
102 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
103 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
104 | curl_setopt($ch, CURLOPT_MAXREDIRS, 1);
105 | curl_setopt($ch, CURLOPT_USERAGENT, 'lscache_runner');
106 | curl_setopt($ch, CURLOPT_ENCODING, "gzip");
107 | curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
108 | if(!empty($cookie)){
109 | curl_setopt($ch, CURLOPT_COOKIE, $cookie);
110 | }
111 |
112 | $buffer = curl_exec($ch);
113 | $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
114 | curl_close($ch);
115 |
116 | if (in_array($httpcode, $acceptCode)) {
117 | echo $current . '/'. $total . ' Warm up: ' . $url . " success!";
118 | } else if($httpcode==428){
119 | echo "Web Server crawler feature not enabled, please check https://www.litespeedtech.com/support/wiki/doku.php/litespeed_wiki:cache:lscwp:configuration:enabling_the_crawler";
120 | break;
121 | } else {
122 | echo $current . '/'. $total . ' Warm up: ' . $url . " failed!";
123 | }
124 |
125 | if($cli) { echo PHP_EOL;}
126 | else { echo "
".PHP_EOL;}
127 | flush();
128 |
129 | }
130 | }
131 |
132 | }
--------------------------------------------------------------------------------
/src/EventSubscriber/LSCacheSubscriber.php:
--------------------------------------------------------------------------------
1 | isMainRequest()) {
18 | return;
19 | }
20 | } else {
21 | if (!$event->isMasterRequest()) {
22 | return;
23 | }
24 | }
25 |
26 | $response = $event->getResponse();
27 | $lscInstance = new LSCacheBackend();
28 |
29 | $purgeTag = $lscInstance->purgeAction();
30 |
31 | if ($purgeTag) {
32 | $response->headers->set(LSCacheBackend::PURGE_HEAD_NAME, $purgeTag);
33 | }
34 |
35 | if($this->isESIrequest()){
36 | $this->handleESI($response);
37 | } else {
38 | $this->handleESIblocks($response);
39 | }
40 | }
41 |
42 | /**
43 | * {@inheritdoc}
44 | */
45 | public static function getSubscribedEvents() {
46 | $events[KernelEvents::RESPONSE][] = ['onRespond', -999];
47 | return $events;
48 | }
49 |
50 |
51 | protected function handleESIblocks($response){
52 | if(!($response instanceof CacheableResponseInterface)){
53 | return;
54 | }
55 | $cache = $response->getCacheableMetadata();
56 | if( $cache->getCacheMaxAge() < 0 ){
57 | return;
58 | }
59 |
60 |
61 | if($response->getStatusCode()!=200){
62 | return;
63 | }
64 | //not logged in
65 | if(empty(\Drupal::currentUser()) || !\Drupal::currentUser()->isAuthenticated()) {
66 | return;
67 | }
68 |
69 | $content = $response->getContent();
70 | if(empty($content)){
71 | return;
72 | }
73 |
74 | $config = \Drupal::config('lite_speed_cache.settings');
75 | $cacheStatus = $config->get('lite_speed_cache.private_cache_status');
76 | if($cacheStatus=='0' or $cacheStatus == 'Off') {
77 | return;
78 | }
79 |
80 | $esi_blocks = $config->get('lite_speed_cache.esi_blocks');
81 | if(empty($esi_blocks)){
82 | return;
83 | }
84 |
85 | if($this->isAdminRoute()){
86 | return;
87 | }
88 |
89 | $dom = new \DOMDocument();
90 | $dom->validateOnParse = true;
91 | $dom->loadHTML($content);
92 |
93 | $blocks = explode(PHP_EOL, $esi_blocks);
94 | $blockElement = false;
95 | foreach($blocks as $block){
96 | if(str_starts_with(trim($block),'id=')){
97 | $blockID = substr(trim($block), 3);
98 | $blockElement = $dom->getElementById($blockID);
99 | if(empty($blockElement)){
100 | continue;
101 | }
102 | $esiElement = $this->getESIelement($dom, $blockID);
103 | $blockElement->parentNode->replaceChild($esiElement,$blockElement);
104 | }
105 | }
106 |
107 | if(empty($blockElement)){
108 | return;
109 | }
110 | $newContent = $dom->saveHTML();
111 | $response->setContent($newContent);
112 | $lscInstance = new LSCacheBackend();
113 |
114 | if($cache->getCacheMaxAge()>0){
115 | $maxAge = $cache->getCacheMaxAge();
116 | } else {
117 | $maxAge = $config->get('lite_speed_cache.max_age');
118 | }
119 |
120 | $response->headers->set('X-LiteSpeed-Cache-Control', 'esi=on, public, max-age='. $maxAge);
121 | $tags = $response->getCacheableMetadata()->getCacheTags();
122 | $tags = $lscInstance->filterTags($tags);
123 | array_unshift($tags, '');
124 | $ftags = $lscInstance->tagCommand('public, ',$tags);
125 | $response->headers->set('X-LiteSpeed-Tag', $ftags);
126 | $lscInstance->checkVary("user:loggedin");
127 | }
128 |
129 |
130 | protected function handleESI($response){
131 | $blockID = \Drupal::request()->query->get('id');
132 | if(empty($blockID)){
133 | return;
134 | }
135 |
136 | $dom = new \DOMDocument();
137 | $dom->loadHTML($response->getContent());
138 |
139 | $blockElement = $dom->getElementById($blockID);
140 | if(empty($blockElement)){
141 | $response->setContent("ESI Block " . $blockID . " does not exist!
");
142 | return;
143 | }
144 |
145 | $newContent = '' . $dom->saveHTML($blockElement) . '';
146 | $response->setContent($newContent);
147 |
148 | $config = \Drupal::config('lite_speed_cache.settings');
149 | $cacheStatus = $config->get('lite_speed_cache.private_cache_status');
150 | if($cacheStatus=='0' or $cacheStatus == 'Off') {
151 | return;
152 | }
153 | $maxAge = $config->get('lite_speed_cache.private_max_age');
154 | $response->headers->set('X-LiteSpeed-Cache-Control', 'esi=on, private, max-age='. $maxAge);
155 | $lscInstance = new LSCacheBackend();
156 | $ftags = $lscInstance->tagCommand('private,', ['',$blockID]);
157 | $response->headers->set('X-LiteSpeed-Tag', $ftags);
158 | $lscInstance->checkPrivateCookie();
159 |
160 | }
161 |
162 |
163 | protected function isESIrequest(){
164 | $current_uri = \Drupal::request()->getRequestUri();
165 | if(str_starts_with($current_uri,'/lscesi')){
166 | return true;
167 | }
168 | return false;
169 | }
170 |
171 | protected function isAdminRoute(){
172 | $route = \Drupal::routeMatch()->getRouteObject();
173 | $is_admin = FALSE;
174 | if (!empty($route)) {
175 | $is_admin_route = \Drupal::service('router.admin_context')->isAdminRoute($route);
176 | $has_node_operation_option = $route->getOption('_node_operation_route');
177 | $is_user_route = str_starts_with($route->getPath(), '/user/') ;
178 | $is_admin = ($is_admin_route || $has_node_operation_option || $is_user_route);
179 | }
180 | else {
181 | $current_path = \Drupal::service('path.current')->getPath();
182 | if(preg_match('/node\/(\d+)\/edit/', $current_path, $matches)) {
183 | $is_admin = TRUE;
184 | }
185 | elseif(preg_match('/taxonomy\/term\/(\d+)\/edit/', $current_path, $matches)) {
186 | $is_admin = TRUE;
187 | }
188 | elseif( str_starts_with($current_path, '/user/')) {
189 | $is_admin = TRUE;
190 | }
191 | }
192 | return $is_admin;
193 | }
194 |
195 | protected function getESIelement($dom, $blockID){
196 | $link = '/lscesi?id=' . $blockID;
197 | $element= $dom->createElement('esi:include');
198 | $element->setAttribute('src', $link);
199 | $element->setAttribute('cache-control', 'private');
200 | return $element;
201 | }
202 |
203 | }
--------------------------------------------------------------------------------
/src/Form/LSCacheForm.php:
--------------------------------------------------------------------------------
1 |
5 | * Date: 1/1/18
6 | * Time: 9:41 PM
7 | */
8 |
9 | namespace Drupal\lite_speed_cache\Form;
10 |
11 | use Drupal\Core\Form\ConfigFormBase;
12 | use Drupal\Core\Form\FormStateInterface;
13 | use Drupal\Core\Messenger\MessengerInterface;
14 | use Drupal\lite_speed_cache\Cache\LSCacheCore;
15 | use Symfony\Component\HttpFoundation\RedirectResponse;
16 | use Drupal\Core\Url;
17 |
18 | class LSCacheForm extends ConfigFormBase
19 | {
20 |
21 | /**
22 | * {@inheritdoc}
23 | */
24 | public function getFormId() {
25 | return 'lite_speed_cache_form';
26 | }
27 |
28 | /**
29 | * {@inheritdoc}
30 | */
31 | protected function getEditableConfigNames() {
32 | return [
33 | 'lite_speed_cache.settings','system.performance',
34 | ];
35 | }
36 |
37 | /**
38 | * {@inheritdoc}
39 | */
40 | public function buildForm(array $form, FormStateInterface $form_state) {
41 | // Form constructor.
42 | $form = parent::buildForm($form, $form_state);
43 | // Default settings.
44 | $config = $this->config('lite_speed_cache.settings');
45 | // esi_on field.
46 |
47 |
48 | $form['clear_cache'] = [
49 | '#type' => 'details',
50 | '#title' => t('LSCache of this site'),
51 | '#open' => TRUE,
52 | ];
53 |
54 | $form['clear_cache']['clear_this'] = [
55 | '#type' => 'submit',
56 | '#value' => t('Clear this site'),
57 | '#submit' => ['::submitClearCache'],
58 | ];
59 |
60 | $form['clear_cache']['warmup_this'] = [
61 | '#type' => 'submit',
62 | '#value' => t('Warm up this site'),
63 | '#submit' => ['::submitWarmup'],
64 | ];
65 |
66 | $form['cache_settings'] = [
67 | '#type' => 'details',
68 | '#title' => t('LSCache Settings'),
69 | '#open' => TRUE,
70 | ];
71 |
72 | $options = ['Off','On'];
73 |
74 | $form['cache_settings']['cache_status'] = array(
75 | '#type' => 'select',
76 | '#title' => $this->t('Cache Status'),
77 | '#options' => $options,
78 | '#default_value' => $config->get('lite_speed_cache.cache_status'),
79 | '#description' => $this->t('Disable or enable LiteSpeed Cache.'),
80 | );
81 |
82 | // max_age field.
83 | $form['cache_settings']['max_age'] = array(
84 | '#type' => 'textfield',
85 | '#title' => $this->t('Public Cache TTL'),
86 | '#default_value' => $config->get('lite_speed_cache.max_age'),
87 | '#description' => $this->t('Amount of time for which page should be cached by LiteSpeed Web Server public cache (Seconds).'),
88 | );
89 |
90 | $options = ['Off','On'];
91 |
92 | $form['cache_settings']['debug'] = array(
93 | '#type' => 'select',
94 | '#title' => $this->t('Debug'),
95 | '#options' => $options,
96 | '#default_value' => $config->get('lite_speed_cache.debug'),
97 | '#description' => $this->t('Weather or not to log debug headers in Log files of web server.'),
98 | );
99 |
100 | $form['cache_login'] = [
101 | '#type' => 'details',
102 | '#title' => t('Private Cache for Logged In Users'),
103 | '#open' => TRUE,
104 | ];
105 |
106 | $options = ['Off','On'];
107 |
108 | $form['cache_login']['private_cache_status'] = array(
109 | '#type' => 'select',
110 | '#title' => $this->t('Private Cache Status'),
111 | '#options' => $options,
112 | '#default_value' => $config->get('lite_speed_cache.private_cache_status'),
113 | '#description' => $this->t('Disable or enable LiteSpeed Private Cache.'),
114 | );
115 |
116 | $form['cache_login']['private_max_age'] = array(
117 | '#type' => 'textfield',
118 | '#title' => $this->t('Private Cache TTL'),
119 | '#default_value' => $config->get('lite_speed_cache.private_max_age'),
120 | '#description' => $this->t('Amount of time for which ESI blocks should be cached by LiteSpeed Web Server private cache (Seconds).'),
121 | );
122 |
123 | $form['cache_login']['esi_blocks'] = array(
124 | '#type' => 'textarea',
125 | '#title' => $this->t('ESI Blocks Setting'),
126 | '#default_value' => $config->get('lite_speed_cache.esi_blocks'),
127 | '#description' => $this->t('ESI Block IDs in Page HTML Source. One block setting per line.'),
128 | '#rows' => 4,
129 | );
130 |
131 | $lscInstance = new LSCacheCore();
132 | $serverType = $lscInstance->getSeverType();
133 | if(!$serverType){
134 | \Drupal::messenger()->addMessage(t('Please use LiteSpeed Web Server to enable Page Cache !'));
135 | }
136 |
137 | return $form;
138 | }
139 |
140 |
141 | /**
142 | * {@inheritdoc}
143 | */
144 | public function validateForm(array &$form, FormStateInterface $form_state) {
145 |
146 | }
147 |
148 | /**
149 | * {@inheritdoc}
150 | */
151 | public function submitForm(array &$form, FormStateInterface $form_state) {
152 | $config = $this->config('lite_speed_cache.settings');
153 | $lscInstance = new LSCacheCore();
154 | $serverType = $lscInstance->getSeverType();
155 | $privateStatus = $form_state->getValue('private_cache_status');
156 | if(($privateStatus) && ($serverType=='LITESPEED_SERVER_OLS')){
157 | \Drupal::messenger()->addMessage(t('OpenLiteSpeed does not support ESI or Private Cache!'));
158 | } else {
159 | $config->set('lite_speed_cache.private_cache_status', $privateStatus);
160 | }
161 |
162 | $config->set('lite_speed_cache.max_age', $form_state->getValue('max_age'));
163 | $config->set('lite_speed_cache.cache_status',$form_state->getValue('cache_status'));
164 | $config->set('lite_speed_cache.debug', $form_state->getValue('debug'));
165 | $config->set('lite_speed_cache.private_max_age', $form_state->getValue('private_max_age'));
166 | $config->set('lite_speed_cache.esi_blocks', $form_state->getValue('esi_blocks'));
167 | $config->save();
168 | return parent::submitForm($form, $form_state);
169 | }
170 |
171 | /**
172 | * Clears this site caches.
173 | */
174 | public function submitClearCache(array &$form, FormStateInterface $form_state) {
175 | $lscInstance = new LSCacheCore();
176 | $lscInstance->purgeAllPublic();
177 | \Drupal::messenger()->addMessage(t('Instructed LiteSpeed Web Server to clear this site cache!'));
178 | }
179 |
180 | /**
181 | * Warmup this site caches.
182 | */
183 | public function submitWarmup(array &$form, FormStateInterface $form_state) {
184 | $path = Url::fromRoute('lite_speed_cache.warmup')->toString();
185 | $response = new RedirectResponse($path,301);
186 | $response->send();
187 | }
188 |
189 | }
--------------------------------------------------------------------------------
/src/LiteSpeedCacheServiceProvider.php:
--------------------------------------------------------------------------------
1 | hasDefinition('cache_factory')) {
19 | $definition = $container->getDefinition('cache_factory');
20 | $definition->setClass('Drupal\lite_speed_cache\Cache\LSCacheBackendFactory');
21 | }
22 | }
23 |
24 | }
--------------------------------------------------------------------------------