Expiration.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OCA\Files_Trashbin;
  8. use OCP\AppFramework\Utility\ITimeFactory;
  9. use OCP\IConfig;
  10. class Expiration {
  11. // how long do we keep files in the trash bin if no other value is defined in the config file (unit: days)
  12. public const DEFAULT_RETENTION_OBLIGATION = 30;
  13. public const NO_OBLIGATION = -1;
  14. /** @var string */
  15. private $retentionObligation;
  16. /** @var int */
  17. private $minAge;
  18. /** @var int */
  19. private $maxAge;
  20. /** @var bool */
  21. private $canPurgeToSaveSpace;
  22. public function __construct(
  23. IConfig $config,
  24. private ITimeFactory $timeFactory,
  25. ) {
  26. $this->setRetentionObligation($config->getSystemValue('trashbin_retention_obligation', 'auto'));
  27. }
  28. public function setRetentionObligation(string $obligation) {
  29. $this->retentionObligation = $obligation;
  30. if ($this->retentionObligation !== 'disabled') {
  31. $this->parseRetentionObligation();
  32. }
  33. }
  34. /**
  35. * Is trashbin expiration enabled
  36. * @return bool
  37. */
  38. public function isEnabled() {
  39. return $this->retentionObligation !== 'disabled';
  40. }
  41. /**
  42. * Check if given timestamp in expiration range
  43. * @param int $timestamp
  44. * @param bool $quotaExceeded
  45. * @return bool
  46. */
  47. public function isExpired($timestamp, $quotaExceeded = false) {
  48. // No expiration if disabled
  49. if (!$this->isEnabled()) {
  50. return false;
  51. }
  52. // Purge to save space (if allowed)
  53. if ($quotaExceeded && $this->canPurgeToSaveSpace) {
  54. return true;
  55. }
  56. $time = $this->timeFactory->getTime();
  57. // Never expire dates in future e.g. misconfiguration or negative time
  58. // adjustment
  59. if ($time < $timestamp) {
  60. return false;
  61. }
  62. // Purge as too old
  63. if ($this->maxAge !== self::NO_OBLIGATION) {
  64. $maxTimestamp = $time - ($this->maxAge * 86400);
  65. $isOlderThanMax = $timestamp < $maxTimestamp;
  66. } else {
  67. $isOlderThanMax = false;
  68. }
  69. if ($this->minAge !== self::NO_OBLIGATION) {
  70. // older than Min obligation and we are running out of quota?
  71. $minTimestamp = $time - ($this->minAge * 86400);
  72. $isMinReached = ($timestamp < $minTimestamp) && $quotaExceeded;
  73. } else {
  74. $isMinReached = false;
  75. }
  76. return $isOlderThanMax || $isMinReached;
  77. }
  78. /**
  79. * @return bool|int
  80. */
  81. public function getMaxAgeAsTimestamp() {
  82. $maxAge = false;
  83. if ($this->isEnabled() && $this->maxAge !== self::NO_OBLIGATION) {
  84. $time = $this->timeFactory->getTime();
  85. $maxAge = $time - ($this->maxAge * 86400);
  86. }
  87. return $maxAge;
  88. }
  89. private function parseRetentionObligation() {
  90. $splitValues = explode(',', $this->retentionObligation);
  91. if (!isset($splitValues[0])) {
  92. $minValue = self::DEFAULT_RETENTION_OBLIGATION;
  93. } else {
  94. $minValue = trim($splitValues[0]);
  95. }
  96. if (!isset($splitValues[1]) && $minValue === 'auto') {
  97. $maxValue = 'auto';
  98. } elseif (!isset($splitValues[1])) {
  99. $maxValue = self::DEFAULT_RETENTION_OBLIGATION;
  100. } else {
  101. $maxValue = trim($splitValues[1]);
  102. }
  103. if ($minValue === 'auto' && $maxValue === 'auto') {
  104. // Default: Keep for 30 days but delete anytime if space needed
  105. $this->minAge = self::DEFAULT_RETENTION_OBLIGATION;
  106. $this->maxAge = self::NO_OBLIGATION;
  107. $this->canPurgeToSaveSpace = true;
  108. } elseif ($minValue !== 'auto' && $maxValue === 'auto') {
  109. // Keep for X days but delete anytime if space needed
  110. $this->minAge = (int)$minValue;
  111. $this->maxAge = self::NO_OBLIGATION;
  112. $this->canPurgeToSaveSpace = true;
  113. } elseif ($minValue === 'auto' && $maxValue !== 'auto') {
  114. // Delete anytime if space needed, Delete all older than max automatically
  115. $this->minAge = self::NO_OBLIGATION;
  116. $this->maxAge = (int)$maxValue;
  117. $this->canPurgeToSaveSpace = true;
  118. } elseif ($minValue !== 'auto' && $maxValue !== 'auto') {
  119. // Delete all older than max OR older than min if space needed
  120. // Max < Min as per https://github.com/owncloud/core/issues/16300
  121. if ($maxValue < $minValue) {
  122. $maxValue = $minValue;
  123. }
  124. $this->minAge = (int)$minValue;
  125. $this->maxAge = (int)$maxValue;
  126. $this->canPurgeToSaveSpace = false;
  127. }
  128. }
  129. }