PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / trunk
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! vtrunk
3.8.0 3.7.5 3.7.4 3.7.3 3.7.2 1-final 3.7.1 3.7.0 3.6.8 3.6.7 3.6.6 3.6.5 3.6.4 3.6.3 3.6.2 3.6.1 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 All 112 releases
templately / modules / utilities / Cleanup / Activation.php

Activation.php in Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! trunk, at modules/utilities/Cleanup/Activation.php

140 lines 4.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The one-time activation gate.
4 *
5 * @package Templately
6 */
7
8 namespace Templately\Modules\Utilities\Cleanup;
9
10 /**
11 * Cleanup deletes NOTHING until an administrator confirms once per site.
12 *
13 * Why the gate exists: every site that has ever abandoned an import is carrying
14 * leftovers today. Without this, the first scheduled run after upgrading would
15 * reclaim a backlog — routinely several gigabytes — with no warning and no way
16 * to look first. Until it is confirmed, every run is a dry run that reports.
17 *
18 * Accepted consequence, decided deliberately: a site whose administrator never
19 * responds reclaims nothing, indefinitely. That is why the prompt lives OUTSIDE
20 * the settings page and stays reachable after dismissal. There is no timed
21 * self-activation — an unactivated site never deletes.
22 *
23 * unactivated ──confirm──▶ activated ──cleanup disabled──▶ unactivated
24 * │ ▲
25 * └──prompt dismissed──▶ unactivated (notice hidden)───────┘
26 */
27 final class Activation {
28
29 const OPTION = 'templately_cleanup_activation';
30
31 public static function state(): array {
32 $stored = get_option( self::OPTION, [] );
33 if ( ! is_array( $stored ) ) {
34 $stored = [];
35 }
36
37 return [
38 'activated' => ! empty( $stored['activated'] ),
39 'activated_at' => isset( $stored['activated_at'] ) ? (int) $stored['activated_at'] : null,
40 'activated_by' => isset( $stored['activated_by'] ) ? (int) $stored['activated_by'] : null,
41 'prompt_dismissed' => ! empty( $stored['prompt_dismissed'] ),
42 'last_estimate_bytes' => RunJournal::last_estimate_bytes(),
43 ];
44 }
45
46 public static function is_activated(): bool {
47 $state = self::state();
48
49 return $state['activated'];
50 }
51
52 /**
53 * The single confirmation. After this, cleanup runs automatically forever —
54 * including for data that accumulates long afterwards. No per-batch approval.
55 */
56 public static function activate( int $user_id = 0 ): array {
57 $state = self::state();
58
59 $state['activated'] = true;
60 $state['activated_at'] = time();
61 $state['activated_by'] = $user_id ?: get_current_user_id();
62
63 return self::save( $state );
64 }
65
66 /**
67 * Return the site to the unactivated state.
68 *
69 * Called when cleanup is switched off: re-enabling it later must ask again,
70 * because the backlog that accumulated while it was off is exactly the
71 * situation the gate exists for.
72 */
73 public static function deactivate(): array {
74 $state = self::state();
75
76 $state['activated'] = false;
77 $state['activated_at'] = null;
78 $state['activated_by'] = null;
79 // The prompt becomes relevant again, so un-dismiss it.
80 $state['prompt_dismissed'] = false;
81
82 return self::save( $state );
83 }
84
85 /**
86 * Hide the notice WITHOUT activating.
87 *
88 * Dismissal is not consent. The tab keeps showing the pending state, and the
89 * prompt must remain reachable — otherwise dismissing it once would silently
90 * strand the site in a state where nothing is ever reclaimed and nothing
91 * ever says so.
92 */
93 public static function dismiss_prompt(): array {
94 $state = self::state();
95 $state['prompt_dismissed'] = true;
96
97 return self::save( $state );
98 }
99
100 /**
101 * Whether the activation prompt should be shown right now.
102 */
103 public static function should_prompt(): bool {
104 if ( Settings::is_disabled() ) {
105 return false;
106 }
107
108 $state = self::state();
109
110 if ( $state['activated'] || $state['prompt_dismissed'] ) {
111 return false;
112 }
113
114 // Nothing to reclaim yet — do not nag a site with a clean uploads dir.
115 return $state['last_estimate_bytes'] > 0;
116 }
117
118 /**
119 * Whether a run must be forced into dry-run regardless of what the caller
120 * asked for.
121 */
122 public static function forces_dry_run(): bool {
123 return ! self::is_activated();
124 }
125
126 private static function save( array $state ): array {
127 // `last_estimate_bytes` is derived from the journal, never stored — a
128 // second copy would go stale the moment a run happened.
129 unset( $state['last_estimate_bytes'] );
130
131 update_option( self::OPTION, $state, false );
132
133 return self::state();
134 }
135
136 public static function reset(): void {
137 delete_option( self::OPTION );
138 }
139 }
140