CompiledFile.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. <?php
  2. /**
  3. * @package Grav.Common.File
  4. *
  5. * @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
  6. * @license MIT License; see LICENSE file for details.
  7. */
  8. namespace Grav\Common\File;
  9. use RocketTheme\Toolbox\File\PhpFile;
  10. trait CompiledFile
  11. {
  12. /**
  13. * Get/set parsed file contents.
  14. *
  15. * @param mixed $var
  16. * @return string
  17. */
  18. public function content($var = null)
  19. {
  20. try {
  21. // If nothing has been loaded, attempt to get pre-compiled version of the file first.
  22. if ($var === null && $this->raw === null && $this->content === null) {
  23. $key = md5($this->filename);
  24. $file = PhpFile::instance(CACHE_DIR . "compiled/files/{$key}{$this->extension}.php");
  25. $modified = $this->modified();
  26. if (!$modified) {
  27. return $this->decode($this->raw());
  28. }
  29. $class = get_class($this);
  30. $cache = $file->exists() ? $file->content() : null;
  31. // Load real file if cache isn't up to date (or is invalid).
  32. if (
  33. !isset($cache['@class'])
  34. || $cache['@class'] !== $class
  35. || $cache['modified'] !== $modified
  36. || $cache['filename'] !== $this->filename
  37. ) {
  38. // Attempt to lock the file for writing.
  39. try {
  40. $file->lock(false);
  41. } catch (\Exception $e) {
  42. // Another process has locked the file; we will check this in a bit.
  43. }
  44. // Decode RAW file into compiled array.
  45. $data = (array)$this->decode($this->raw());
  46. $cache = [
  47. '@class' => $class,
  48. 'filename' => $this->filename,
  49. 'modified' => $modified,
  50. 'data' => $data
  51. ];
  52. // If compiled file wasn't already locked by another process, save it.
  53. if ($file->locked() !== false) {
  54. $file->save($cache);
  55. $file->unlock();
  56. // Compile cached file into bytecode cache
  57. if (function_exists('opcache_invalidate')) {
  58. // Silence error if function exists, but is restricted.
  59. @opcache_invalidate($file->filename(), true);
  60. }
  61. }
  62. }
  63. $file->free();
  64. $this->content = $cache['data'];
  65. }
  66. } catch (\Exception $e) {
  67. throw new \RuntimeException(sprintf('Failed to read %s: %s', basename($this->filename), $e->getMessage()), 500, $e);
  68. }
  69. return parent::content($var);
  70. }
  71. /**
  72. * Serialize file.
  73. */
  74. public function __sleep()
  75. {
  76. return [
  77. 'filename',
  78. 'extension',
  79. 'raw',
  80. 'content',
  81. 'settings'
  82. ];
  83. }
  84. /**
  85. * Unserialize file.
  86. */
  87. public function __wakeup()
  88. {
  89. if (!isset(static::$instances[$this->filename])) {
  90. static::$instances[$this->filename] = $this;
  91. }
  92. }
  93. }