advanced-pagecache.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. <?php
  2. namespace Grav\Plugin;
  3. use Grav\Common\Config\Config;
  4. use Grav\Common\Page\Interfaces\PageInterface;
  5. use Grav\Common\Plugin;
  6. use Grav\Common\Uri;
  7. use Grav\Framework\Psr7\Response;
  8. use RocketTheme\Toolbox\Event\Event;
  9. /**
  10. * Class AdvancedPageCachePlugin
  11. * @package Grav\Plugin
  12. */
  13. class AdvancedPageCachePlugin extends Plugin
  14. {
  15. /** @var Config $config */
  16. protected $config;
  17. /** @var string */
  18. protected $pagecache_key;
  19. /**
  20. * @return array
  21. */
  22. public static function getSubscribedEvents()
  23. {
  24. return [
  25. 'onPluginsInitialized' => ['onPluginsInitialized', 1000]
  26. ];
  27. }
  28. /**
  29. * Return `true` if the page has no extension, or has the default page extension.
  30. * Return `false` if for example is a RSS version of the page
  31. */
  32. private function isValidExtension() : bool
  33. {
  34. /** @var Uri $uri */
  35. $uri = $this->grav['uri'];
  36. $extension = $uri->extension();
  37. if (!$extension) {
  38. return true;
  39. }
  40. $disabled_extensions = (array)$this->grav['config']->get('plugins.advanced-pagecache.disabled_extensions');
  41. return !in_array($extension, $disabled_extensions, true);
  42. }
  43. /**
  44. * Initialize configuration
  45. */
  46. public function onPluginsInitialized(): void
  47. {
  48. /** @var Uri $uri */
  49. $uri = $this->grav['uri'];
  50. $config = (array)$this->grav['config']->get('plugins.advanced-pagecache');
  51. $full_route = $uri->uri();
  52. $route = str_replace($uri->baseIncludingLanguage(), '', $full_route);
  53. $params = $uri->params(null, true);
  54. $query = $uri->query(null, true);
  55. $user = $this->grav['user'] ?? null;
  56. $lang = $this->grav['language']->getLanguageURLPrefix();
  57. // Definitely don't run in admin plugin or is not a valid extension
  58. if ($this->isAdmin() || !$this->isValidExtension()) {
  59. return;
  60. }
  61. // If this url is not whitelisted try some other tests
  62. if (!in_array($route, (array)$config['whitelist'], true)) {
  63. // do not run in these scenarios
  64. if (
  65. ($config['disabled_with_params'] && !empty($params)) ||
  66. ($config['disabled_with_query'] && !empty($query)) ||
  67. ($config['disabled_on_login'] && ($user && $user["authenticated"])) ||
  68. in_array($route, (array)$config['blacklist'], true)
  69. ) {
  70. return;
  71. }
  72. }
  73. // Should run and store page
  74. if ($config['per_user_caching']) {
  75. $this->pagecache_key = md5('adv-pc-' . $lang . $full_route . $user["username"]);
  76. } else {
  77. $this->pagecache_key = md5('adv-pc-' . $lang . $full_route);
  78. }
  79. // TODO: remove when minimum required Grav >= 1.7.15
  80. if (version_compare($this->grav->getVersion(), '1.7.15', '<')) {
  81. $this->enable([
  82. 'onOutputGenerated' => ['onOutputGenerated', -1000]
  83. ]);
  84. } else {
  85. $this->enable([
  86. 'onOutputRendered' => ['onOutputRendered', 1000]
  87. ]);
  88. }
  89. $pageCache = $this->grav['cache']->fetch($this->pagecache_key);
  90. if (is_array($pageCache)) {
  91. $response = new Response($pageCache['code'], $pageCache['headers'], $pageCache['html']);
  92. $this->grav->close($response);
  93. }
  94. }
  95. /**
  96. * Save the page to the cache
  97. * TODO: remove when minimum required Grav >= 1.7.15
  98. */
  99. public function onOutputGenerated(Event $event): void
  100. {
  101. /** @var PageInterface $page */
  102. $page = $this->grav['page'];
  103. $html = $this->grav->output;
  104. $item = [
  105. 'code' => $page->httpResponseCode(),
  106. 'headers' => $page->httpHeaders(),
  107. 'html' => $html,
  108. ];
  109. $this->grav['cache']->save($this->pagecache_key, $item);
  110. }
  111. /**
  112. * Save the page to the cache
  113. */
  114. public function onOutputRendered(Event $event): void
  115. {
  116. /** @var PageInterface $page */
  117. $page = $event['page'];
  118. $html = $event['output'];
  119. $item = [
  120. 'code' => $page->httpResponseCode(),
  121. 'headers' => $page->httpHeaders(),
  122. 'html' => $html,
  123. ];
  124. $this->grav['cache']->save($this->pagecache_key, $item);
  125. }
  126. }